[vm/concurrency] Use isolate group id as key for incremental compiler for reload

As part of implementing hot-reload for isolate groups, we have to ensure
reloads on a group are performed using the same state of incremental
compiler.

This means we cannot use a specific isolate's information (such as it's
main port) for reloading purposes. Instead we use the unqiue isolate
group id when communicating with the kernel service.

Issue https://github.com/dart-lang/sdk/issues/36097

TEST=Existing test coverage, future test when hot-reload is fully
     implemented with isolate groups.

Change-Id: Ifab39cd2ba689c08507dfab4091cd26951ed54e5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/185320
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann
2021-02-18 06:59:24 +00:00
committed by commit-bot@chromium.org
parent 6ce172d87f
commit 2e2d542969
9 changed files with 81 additions and 82 deletions
+46 -47
View File
@@ -153,7 +153,7 @@ CompilerOptions setupCompilerOptions(
}
abstract class Compiler {
final int isolateId;
final int isolateGroupId;
final FileSystem fileSystem;
final Uri platformKernelPath;
final bool enableAsserts;
@@ -172,7 +172,7 @@ abstract class Compiler {
CompilerOptions options;
Compiler(this.isolateId, this.fileSystem, this.platformKernelPath,
Compiler(this.isolateGroupId, this.fileSystem, this.platformKernelPath,
{this.enableAsserts: false,
this.nullSafety: kNullSafetyOptionUnspecified,
this.experimentalFlags: null,
@@ -214,7 +214,7 @@ abstract class Compiler {
if (errors.isEmpty) {
// Record dependencies only if compilation was error free.
_recordDependencies(isolateId, component, options.packagesFileUri);
_recordDependencies(isolateGroupId, component, options.packagesFileUri);
}
return compilerResult;
@@ -289,14 +289,14 @@ class IncrementalCompilerWrapper extends Compiler {
IncrementalCompiler generator;
IncrementalCompilerWrapper(
int isolateId, FileSystem fileSystem, Uri platformKernelPath,
int isolateGroupId, FileSystem fileSystem, Uri platformKernelPath,
{bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
List<String> experimentalFlags: null,
String packageConfig: null,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue})
: super(isolateId, fileSystem, platformKernelPath,
: super(isolateGroupId, fileSystem, platformKernelPath,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
experimentalFlags: experimentalFlags,
@@ -308,7 +308,7 @@ class IncrementalCompilerWrapper extends Compiler {
factory IncrementalCompilerWrapper.forExpressionCompilationOnly(
Component component,
int isolateId,
int isolateGroupId,
FileSystem fileSystem,
Uri platformKernelPath,
{bool enableAsserts: false,
@@ -316,7 +316,7 @@ class IncrementalCompilerWrapper extends Compiler {
String packageConfig: null,
String invocationModes: ''}) {
IncrementalCompilerWrapper result = IncrementalCompilerWrapper(
isolateId, fileSystem, platformKernelPath,
isolateGroupId, fileSystem, platformKernelPath,
enableAsserts: enableAsserts,
experimentalFlags: experimentalFlags,
packageConfig: packageConfig,
@@ -342,9 +342,9 @@ class IncrementalCompilerWrapper extends Compiler {
void accept() => generator.accept();
void invalidate(Uri uri) => generator.invalidate(uri);
Future<IncrementalCompilerWrapper> clone(int isolateId) async {
Future<IncrementalCompilerWrapper> clone(int isolateGroupId) async {
IncrementalCompilerWrapper clone = IncrementalCompilerWrapper(
isolateId, fileSystem, platformKernelPath,
isolateGroupId, fileSystem, platformKernelPath,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
experimentalFlags: experimentalFlags,
@@ -359,7 +359,7 @@ class IncrementalCompilerWrapper extends Compiler {
// clone should be used for.
MemoryFileSystem memoryFileSystem = (fileSystem as HybridFileSystem).memory;
String filename = 'full-component-$isolateId.dill';
String filename = 'full-component-$isolateGroupId.dill';
Sink sink = FileSink(memoryFileSystem.entityForUri(Uri.file(filename)));
new BinaryPrinter(sink).writeComponentFile(fullComponent);
await sink.close();
@@ -374,7 +374,7 @@ class SingleShotCompilerWrapper extends Compiler {
final bool requireMain;
SingleShotCompilerWrapper(
int isolateId, FileSystem fileSystem, Uri platformKernelPath,
int isolateGroupId, FileSystem fileSystem, Uri platformKernelPath,
{this.requireMain: false,
bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
@@ -382,7 +382,7 @@ class SingleShotCompilerWrapper extends Compiler {
String packageConfig: null,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue})
: super(isolateId, fileSystem, platformKernelPath,
: super(isolateGroupId, fileSystem, platformKernelPath,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
experimentalFlags: experimentalFlags,
@@ -405,18 +405,15 @@ class SingleShotCompilerWrapper extends Compiler {
}
}
// TODO(33428): This state is leaked on isolate shutdown.
final Map<int, IncrementalCompilerWrapper> isolateCompilers =
new Map<int, IncrementalCompilerWrapper>();
final Map<int, List<Uri>> isolateDependencies = new Map<int, List<Uri>>();
final Map<int, _ExpressionCompilationFromDillSettings> isolateLoadNotifies =
new Map<int, _ExpressionCompilationFromDillSettings>();
final Map<int, IncrementalCompilerWrapper> isolateCompilers = {};
final Map<int, List<Uri>> isolateDependencies = {};
final Map<int, _ExpressionCompilationFromDillSettings> isolateLoadNotifies = {};
IncrementalCompilerWrapper lookupIncrementalCompiler(int isolateId) {
return isolateCompilers[isolateId];
IncrementalCompilerWrapper lookupIncrementalCompiler(int isolateGroupId) {
return isolateCompilers[isolateGroupId];
}
Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateGroupId,
List sourceFiles, Uri platformKernelPath, List<int> platformKernel,
{bool enableAsserts: false,
int nullSafety: kNullSafetyOptionUnspecified,
@@ -426,7 +423,8 @@ Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
String multirootScheme,
String invocationModes: '',
String verbosityLevel: Verbosity.defaultValue}) async {
IncrementalCompilerWrapper compiler = lookupIncrementalCompiler(isolateId);
IncrementalCompilerWrapper compiler =
lookupIncrementalCompiler(isolateGroupId);
if (compiler != null) {
updateSources(compiler, sourceFiles);
invalidateSources(compiler, sourceFiles);
@@ -439,7 +437,7 @@ Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
sourceFiles[1] == null) {
// Just use first compiler that should represent main isolate as a source for cloning.
var source = isolateCompilers.entries.first;
compiler = await source.value.clone(isolateId);
compiler = await source.value.clone(isolateGroupId);
} else {
FileSystem fileSystem = _buildFileSystem(
sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
@@ -449,7 +447,7 @@ Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
// isolate needs to receive a message indicating that particular
// isolate was shut down. Message should be handled here in this script.
compiler = new IncrementalCompilerWrapper(
isolateId, fileSystem, platformKernelPath,
isolateGroupId, fileSystem, platformKernelPath,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
experimentalFlags: experimentalFlags,
@@ -457,7 +455,7 @@ Future<Compiler> lookupOrBuildNewIncrementalCompiler(int isolateId,
invocationModes: invocationModes,
verbosityLevel: verbosityLevel);
}
isolateCompilers[isolateId] = compiler;
isolateCompilers[isolateGroupId] = compiler;
}
return compiler;
}
@@ -494,7 +492,7 @@ void invalidateSources(IncrementalCompilerWrapper compiler, List sourceFiles) {
// kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
Future _processExpressionCompilationRequest(request) async {
final SendPort port = request[1];
final int isolateId = request[2];
final int isolateGroupId = request[2];
final dynamic dart_platform_kernel = request[3];
final String expression = request[4];
final List<String> definitions = request[5].cast<String>();
@@ -508,15 +506,15 @@ Future _processExpressionCompilationRequest(request) async {
final List<String> experimentalFlags =
request[13] != null ? request[13].cast<String>() : null;
IncrementalCompilerWrapper compiler = isolateCompilers[isolateId];
IncrementalCompilerWrapper compiler = isolateCompilers[isolateGroupId];
_ExpressionCompilationFromDillSettings isolateLoadDillData =
isolateLoadNotifies[isolateId];
isolateLoadNotifies[isolateGroupId];
if (isolateLoadDillData != null) {
// Check if we can reuse the compiler.
if (isolateLoadDillData.blobLoadCount != blobLoadCount ||
isolateLoadDillData.prevDillCount != dillData.length) {
compiler = isolateCompilers[isolateId] = null;
compiler = isolateCompilers[isolateGroupId] = null;
}
}
@@ -525,7 +523,7 @@ Future _processExpressionCompilationRequest(request) async {
if (verbose) {
print("DFE: Initializing compiler from ${dillData.length} dill files");
}
isolateLoadNotifies[isolateId] =
isolateLoadNotifies[isolateGroupId] =
new _ExpressionCompilationFromDillSettings(
blobLoadCount, dillData.length);
@@ -585,11 +583,11 @@ Future _processExpressionCompilationRequest(request) async {
// isolate was shut down. Message should be handled here in this script.
try {
compiler = new IncrementalCompilerWrapper.forExpressionCompilationOnly(
component, isolateId, fileSystem, null,
component, isolateGroupId, fileSystem, null,
enableAsserts: enableAsserts,
experimentalFlags: experimentalFlags,
packageConfig: dotPackagesFile);
isolateCompilers[isolateId] = compiler;
isolateCompilers[isolateGroupId] = compiler;
await compiler.compile(
component.mainMethod?.enclosingLibrary?.importUri ??
component.libraries.last.importUri);
@@ -640,8 +638,8 @@ Future _processExpressionCompilationRequest(request) async {
}
void _recordDependencies(
int isolateId, Component component, Uri packageConfig) {
final dependencies = isolateDependencies[isolateId] ??= <Uri>[];
int isolateGroupId, Component component, Uri packageConfig) {
final dependencies = isolateDependencies[isolateGroupId] ??= <Uri>[];
if (component != null) {
for (var lib in component.libraries) {
@@ -673,8 +671,9 @@ List<int> _serializeDependencies(List<Uri> uris) {
return utf8.encode(uris.map(_escapeDependency).join(" "));
}
Future _processListDependenciesRequest(SendPort port, int isolateId) async {
final List<Uri> dependencies = isolateDependencies[isolateId] ?? <Uri>[];
Future _processListDependenciesRequest(
SendPort port, int isolateGroupId) async {
final List<Uri> dependencies = isolateDependencies[isolateGroupId] ?? <Uri>[];
CompilationResult result;
try {
@@ -687,10 +686,10 @@ Future _processListDependenciesRequest(SendPort port, int isolateId) async {
}
Future _processIsolateShutdownNotification(request) async {
final int isolateId = request[1];
isolateCompilers.remove(isolateId);
isolateDependencies.remove(isolateId);
isolateLoadNotifies.remove(isolateId);
final int isolateGroupId = request[1];
isolateCompilers.remove(isolateGroupId);
isolateDependencies.remove(isolateGroupId);
isolateLoadNotifies.remove(isolateGroupId);
}
Future _processLoadRequest(request) async {
@@ -733,10 +732,10 @@ Future _processLoadRequest(request) async {
}
final SendPort port = request[1];
final int isolateId = request[7];
final int isolateGroupId = request[7];
if (tag == kListDependenciesTag) {
await _processListDependenciesRequest(port, isolateId);
await _processListDependenciesRequest(port, isolateGroupId);
return;
}
@@ -777,7 +776,7 @@ Future _processLoadRequest(request) async {
if (tag == kUpdateSourcesTag) {
assert(incremental,
"Incremental compiler required for use of 'kUpdateSourcesTag'");
compiler = lookupIncrementalCompiler(isolateId);
compiler = lookupIncrementalCompiler(isolateGroupId);
if (compiler == null) {
port.send(new CompilationResult.errors(
["No incremental compiler available for this isolate."], null)
@@ -790,7 +789,7 @@ Future _processLoadRequest(request) async {
} else if (tag == kAcceptTag) {
assert(
incremental, "Incremental compiler required for use of 'kAcceptTag'");
compiler = lookupIncrementalCompiler(isolateId);
compiler = lookupIncrementalCompiler(isolateGroupId);
// There are unit tests that invoke the IncrementalCompiler directly and
// request a reload, meaning that we won't have a compiler for this isolate.
if (compiler != null) {
@@ -841,7 +840,7 @@ Future _processLoadRequest(request) async {
// watch the performance though.
if (incremental) {
compiler = await lookupOrBuildNewIncrementalCompiler(
isolateId, sourceFiles, platformKernelPath, platformKernel,
isolateGroupId, sourceFiles, platformKernelPath, platformKernel,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
experimentalFlags: experimentalFlags,
@@ -854,7 +853,7 @@ Future _processLoadRequest(request) async {
FileSystem fileSystem = _buildFileSystem(
sourceFiles, platformKernel, multirootFilepaths, multirootScheme);
compiler = new SingleShotCompilerWrapper(
isolateId, fileSystem, platformKernelPath,
isolateGroupId, fileSystem, platformKernelPath,
requireMain: false,
enableAsserts: enableAsserts,
nullSafety: nullSafety,
@@ -1007,7 +1006,7 @@ Future trainInternal(String scriptUri, String platformKernelPath) async {
false /* incremental */,
false /* snapshot */,
kNullSafetyOptionUnspecified /* null safety */,
1 /* isolateId chosen randomly */,
1 /* isolateGroupId chosen randomly */,
[] /* source files */,
false /* enable asserts */,
null /* experimental_flags */,
+3 -3
View File
@@ -886,10 +886,10 @@ static const char* CanonicalizeUri(Thread* thread,
char** error) {
const char* result = NULL;
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
if (isolate->HasTagHandler()) {
auto isolate_group = thread->isolate_group();
if (isolate_group->HasTagHandler()) {
const Object& obj = Object::Handle(
isolate->CallTagHandler(Dart_kCanonicalizeUrl, library, uri));
isolate_group->CallTagHandler(Dart_kCanonicalizeUrl, library, uri));
if (obj.IsString()) {
result = String2UTF8(String::Cast(obj));
} else if (obj.IsError()) {
+3 -3
View File
@@ -662,7 +662,7 @@ static void ThrowLanguageError(const char* message) {
DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0));
if (!isolate->HasTagHandler()) {
if (!isolate->group()->HasTagHandler()) {
ThrowLanguageError("no library handler registered");
}
@@ -675,7 +675,7 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 0, 1) {
} else {
isolate->BlockClassFinalization();
const Object& result = Object::Handle(
zone, isolate->CallTagHandler(
zone, isolate->group()->CallTagHandler(
Dart_kCanonicalizeUrl,
Library::Handle(
zone, isolate->group()->object_store()->root_library()),
@@ -703,7 +703,7 @@ DEFINE_NATIVE_ENTRY(IsolateMirror_loadUri, 0, 1) {
// Request the embedder to load the library.
isolate->BlockClassFinalization();
Object& result = Object::Handle(
zone, isolate->CallTagHandler(
zone, isolate->group()->CallTagHandler(
Dart_kImportTag,
Library::Handle(
zone, isolate->group()->object_store()->root_library()),
+6 -5
View File
@@ -1895,9 +1895,9 @@ Thread* Isolate::mutator_thread() const {
return mutator_thread_;
}
ObjectPtr Isolate::CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2) {
ObjectPtr IsolateGroup::CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2) {
Thread* thread = Thread::Current();
Api::Scope api_scope(thread);
Dart_Handle api_arg1 = Api::NewHandle(thread, arg1.ptr());
@@ -1906,7 +1906,7 @@ ObjectPtr Isolate::CallTagHandler(Dart_LibraryTag tag,
{
TransitionVMToNative transition(thread);
ASSERT(HasTagHandler());
api_result = group()->library_tag_handler()(tag, api_arg1, api_arg2);
api_result = library_tag_handler()(tag, api_arg1, api_arg2);
}
return Api::UnwrapHandle(api_result);
}
@@ -2473,7 +2473,6 @@ void Isolate::Shutdown() {
StackZone zone(thread);
HandleScope handle_scope(thread);
ServiceIsolate::SendIsolateShutdownMessage();
KernelIsolate::NotifyAboutIsolateShutdown(this);
#if !defined(PRODUCT)
debugger()->Shutdown();
#endif
@@ -2545,6 +2544,8 @@ void Isolate::LowLevelCleanup(Isolate* isolate) {
const bool shutdown_group =
isolate_group->UnregisterIsolateDecrementCount(isolate);
if (shutdown_group) {
KernelIsolate::NotifyAboutIsolateGroupShutdown(isolate_group);
#if !defined(DART_PRECOMPILED_RUNTIME)
if (!is_vm_isolate) {
Thread::EnterIsolateGroupAsHelper(isolate_group, Thread::kUnknownTask,
+5 -7
View File
@@ -600,6 +600,10 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
void IncreaseMutatorCount(Isolate* mutator);
void DecreaseMutatorCount(Isolate* mutator);
bool HasTagHandler() const { return library_tag_handler() != nullptr; }
ObjectPtr CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2);
Dart_LibraryTagHandler library_tag_handler() const {
return library_tag_handler_;
}
@@ -724,7 +728,7 @@ class IsolateGroup : public IntrusiveDListEntry<IsolateGroup> {
#endif
}
uint64_t id() { return id_; }
uint64_t id() const { return id_; }
static void Init();
static void Cleanup();
@@ -1102,12 +1106,6 @@ class Isolate : public BaseIsolate, public IntrusiveDListEntry<Isolate> {
environment_callback_ = value;
}
bool HasTagHandler() const {
return group()->library_tag_handler() != nullptr;
}
ObjectPtr CallTagHandler(Dart_LibraryTag tag,
const Object& arg1,
const Object& arg2);
bool HasDeferredLoadHandler() const {
return group()->deferred_load_handler() != nullptr;
}
+4 -4
View File
@@ -194,18 +194,18 @@ std::unique_ptr<Program> Program::ReadFrom(Reader* reader, const char** error) {
std::unique_ptr<Program> Program::ReadFromFile(
const char* script_uri, const char** error /* = nullptr */) {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
auto isolate_group = thread->isolate_group();
if (script_uri == NULL) {
return nullptr;
}
if (!isolate->HasTagHandler()) {
if (!isolate_group->HasTagHandler()) {
return nullptr;
}
std::unique_ptr<kernel::Program> kernel_program;
const String& uri = String::Handle(String::New(script_uri));
const Object& ret = Object::Handle(
isolate->CallTagHandler(Dart_kKernelTag, Object::null_object(), uri));
const Object& ret = Object::Handle(isolate_group->CallTagHandler(
Dart_kKernelTag, Object::null_object(), uri));
if (ret.IsExternalTypedData()) {
const auto& typed_data = ExternalTypedData::Handle(
thread->zone(), ExternalTypedData::RawCast(ret.ptr()));
+8 -9
View File
@@ -559,13 +559,12 @@ class KernelCompilationRequest : public ValueObject {
is_static_object.type = Dart_CObject_kBool;
is_static_object.value.as_bool = is_static;
auto isolate = thread->isolate();
auto isolate_group = thread->isolate_group();
auto source = isolate_group->source();
Dart_CObject isolate_id;
isolate_id.type = Dart_CObject_kInt64;
isolate_id.value.as_int64 = static_cast<int64_t>(isolate->main_port());
isolate_id.value.as_int64 = static_cast<int64_t>(isolate_group->id());
intptr_t num_dills = 0;
if (source->kernel_buffer != nullptr) {
@@ -756,16 +755,16 @@ class KernelCompilationRequest : public ValueObject {
// compilation logic out of CreateIsolateAndSetupHelper and into
// IsolateSetupHelper in main.cc.
auto thread = Thread::Current();
auto isolate = thread != nullptr ? thread->isolate() : nullptr;
auto isolate_group = thread != nullptr ? thread->isolate_group() : nullptr;
if (incremental_compile) {
ASSERT(isolate != NULL);
ASSERT(isolate_group != nullptr);
}
Dart_CObject isolate_id;
isolate_id.type = Dart_CObject_kInt64;
isolate_id.value.as_int64 =
isolate != nullptr ? static_cast<int64_t>(isolate->main_port()) : 0;
isolate_id.value.as_int64 = isolate_group != nullptr
? static_cast<int64_t>(isolate_group->id())
: 0;
Dart_CObject message;
message.type = Dart_CObject_kArray;
@@ -1155,7 +1154,8 @@ Dart_KernelCompilationResult KernelIsolate::UpdateInMemorySources(
Dart_KernelCompilationVerbosityLevel_Error);
}
void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) {
void KernelIsolate::NotifyAboutIsolateGroupShutdown(
const IsolateGroup* isolate_group) {
if (!KernelIsolate::IsRunning()) {
return;
}
@@ -1170,8 +1170,7 @@ void KernelIsolate::NotifyAboutIsolateShutdown(const Isolate* isolate) {
Dart_CObject isolate_id;
isolate_id.type = Dart_CObject_kInt64;
isolate_id.value.as_int64 =
isolate != NULL ? static_cast<int64_t>(isolate->main_port()) : 0;
isolate_id.value.as_int64 = static_cast<int64_t>(isolate_group->id());
Dart_CObject message;
message.type = Dart_CObject_kArray;
+4 -2
View File
@@ -79,7 +79,8 @@ class KernelIsolate : public AllStatic {
static Dart_KernelCompilationResult ListDependencies();
static void NotifyAboutIsolateShutdown(const Isolate* isolate);
static void NotifyAboutIsolateGroupShutdown(
const IsolateGroup* isolate_group);
static void AddExperimentalFlag(const char* value);
static bool GetExperimentalFlag(ExperimentalFeature feature);
@@ -115,7 +116,8 @@ class KernelIsolate : public AllStatic {
static bool IsRunning() { return false; }
static void Shutdown() {}
static bool IsKernelIsolate(const Isolate* isolate) { return false; }
static void NotifyAboutIsolateShutdown(const Isolate* isolate) {}
static void NotifyAboutIsolateGroupShutdown(
const IsolateGroup* isolate_group) {}
static bool GetExperimentalFlag(const char* value) { return false; }
protected:
+2 -2
View File
@@ -704,13 +704,13 @@ void KernelLoader::LoadNativeExtensionLibraries() {
void KernelLoader::LoadNativeExtension(const Library& library,
const String& uri_path) {
#if !defined(DART_PRECOMPILER)
if (!I->HasTagHandler()) {
if (!IG->HasTagHandler()) {
H.ReportError("no library handler registered.");
}
I->BlockClassFinalization();
const auto& result = Object::Handle(
Z, I->CallTagHandler(Dart_kImportExtensionTag, library, uri_path));
Z, IG->CallTagHandler(Dart_kImportExtensionTag, library, uri_path));
I->UnblockClassFinalization();
if (result.IsError()) {