Skip to content

Commit 016041e

Browse files
authored
Remove remainder of support for external startup data (#1758)
* feat: Remove V8 heap snapshot machinery As per NativeScript/NativeScript#8926, this isn't supported. "heapSnapshotScript" and "heapSnapshotBlob" keys in package.json will be ignored, but I believe this isn't a breaking change because I think they were already nonfunctional. The V8 library is updated with a build configured with v8_use_external_startup_data=false, and we can remove the snapshot_blob.h files because the snapshot data no longer needs to be compiled into the runtime. The V8 artifacts were built using NativeScript/v8-buildscripts and GitHub Actions, with the following provenance: arm64: commit 0368bca, job https://github.com/NativeScript/v8-buildscripts/actions/runs/4895461273 arm: commit b074e10, job https://github.com/NativeScript/v8-buildscripts/actions/runs/4895462464 x86_64: commit a9bf41b, job https://github.com/NativeScript/v8-buildscripts/actions/runs/4895463287 x86: commit e7aa7ed, job https://github.com/NativeScript/v8-buildscripts/actions/runs/4895464030 * chore: Remove File::Exists() This was primarily used by the heap snapshot code which is now removed. It was also used internally in File::ReadBinary(), but that wasn't necessary, as fopen() also handles the file not existing. In new code, it's probably a good idea to perform operations without checking if the file exists first anyway, as otherwise it can lead to race conditions if the file is deleted. * chore: Remove MemoryMappedFile This was only used by the snapshot code, which is now removed.
1 parent ff1b979 commit 016041e

File tree

19 files changed

+4
-17635
lines changed

19 files changed

+4
-17635
lines changed

test-app/app/src/main/java/com/tns/RuntimeHelper.java

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,6 @@ public static Runtime initRuntime(Context context) {
112112
aE.extractAssets(context, "internal", outputDir, extractPolicy, removePreviouslyInstalledAssets);
113113
aE.extractAssets(context, "metadata", outputDir, extractPolicy, false);
114114

115-
boolean shouldExtractSnapshots = true;
116-
117-
// will extract snapshot of the device appropriate architecture
118-
if (shouldExtractSnapshots) {
119-
if (logger.isEnabled()) {
120-
logger.write("Extracting snapshot blob");
121-
}
122-
123-
@SuppressWarnings("deprecation")
124-
String cpu_abi = Build.CPU_ABI;
125-
aE.extractAssets(context, "snapshots/" + cpu_abi, outputDir, extractPolicy, removePreviouslyInstalledAssets);
126-
}
127-
128115
extractPolicy.setAssetsThumb(context);
129116
} finally {
130117
extractionFrame.close();

test-app/runtime/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,6 @@ include_directories(
5252
src/main/cpp
5353
src/main/cpp/include
5454
src/main/cpp/v8_inspector
55-
# This folder contains V8's built-in natives and snapshot blobs
56-
src/main/libs/${ANDROID_ABI}/include
5755
)
5856

5957
if (OPTIMIZED_BUILD OR OPTIMIZED_WITH_INSPECTOR_BUILD)

test-app/runtime/src/main/cpp/Constants.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,3 @@
1010
std::string Constants::APP_ROOT_FOLDER_PATH = "";
1111
bool Constants::V8_CACHE_COMPILED_CODE = false;
1212
std::string Constants::V8_STARTUP_FLAGS = "";
13-
std::string Constants::V8_HEAP_SNAPSHOT_SCRIPT = "";
14-
std::string Constants::V8_HEAP_SNAPSHOT_BLOB = "";

test-app/runtime/src/main/cpp/Constants.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ class Constants {
99

1010
static std::string APP_ROOT_FOLDER_PATH;
1111
static std::string V8_STARTUP_FLAGS;
12-
static std::string V8_HEAP_SNAPSHOT_SCRIPT;
13-
static std::string V8_HEAP_SNAPSHOT_BLOB;
1412
static bool V8_CACHE_COMPILED_CODE;
1513

1614
private:

test-app/runtime/src/main/cpp/File.cpp

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
using namespace std;
1515

1616
namespace tns {
17-
bool File::Exists(const string& path) {
18-
std::ifstream infile(path.c_str());
19-
return infile.good();
20-
}
17+
2118
string File::ReadText(const string& filePath) {
2219
int len;
2320
bool isNew;
@@ -34,9 +31,6 @@ string File::ReadText(const string& filePath) {
3431

3532
void* File::ReadBinary(const string& filePath, int& length) {
3633
length = 0;
37-
if (!File::Exists(filePath)) {
38-
return nullptr;
39-
}
4034

4135
auto file = fopen(filePath.c_str(), READ_BINARY);
4236
if (!file) {
@@ -89,34 +83,6 @@ const char* File::ReadText(const string& filePath, int& charLength, bool& isNew)
8983
return Buffer;
9084
}
9185

92-
MemoryMappedFile MemoryMappedFile::Open(const char* filePath) {
93-
void* memory = nullptr;
94-
int length = 0;
95-
if (FILE* file = fopen(filePath, "r+")) {
96-
if (fseek(file, 0, SEEK_END) == 0) {
97-
length = ftell(file);
98-
if (length >= 0) {
99-
memory = mmap(NULL, length, PROT_READ, MAP_SHARED, fileno(file), 0);
100-
if (memory == MAP_FAILED) {
101-
memory = nullptr;
102-
}
103-
}
104-
}
105-
fclose(file);
106-
}
107-
return MemoryMappedFile(memory, length);
108-
}
109-
110-
MemoryMappedFile::MemoryMappedFile(void* memory, size_t size)
111-
:
112-
memory(memory), size(size) {
113-
}
114-
115-
MemoryMappedFile::~MemoryMappedFile() {
116-
int result = munmap(this->memory, this->size);
117-
assert(result == 0);
118-
}
119-
12086
char* File::Buffer = new char[BUFFER_SIZE];
12187

12288
const char* File::WRITE_BINARY = "wb";

test-app/runtime/src/main/cpp/File.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,10 @@
1111
#include <string>
1212

1313
namespace tns {
14-
struct MemoryMappedFile final {
15-
static MemoryMappedFile Open(const char* filePath);
16-
MemoryMappedFile(void* memory, size_t size);
17-
~MemoryMappedFile();
18-
19-
void* memory = nullptr;
20-
size_t size = 0;
21-
};
22-
2314
class File {
2415
public:
2516
static const char* ReadText(const std::string& filePath, int& length, bool& isNew);
2617
static std::string ReadText(const std::string& filePath);
27-
static bool Exists(const std::string& filePath);
2818
static bool WriteBinary(const std::string& filePath, const void* inData, int length);
2919
static void* ReadBinary(const std::string& filePath, int& length);
3020
private:

test-app/runtime/src/main/cpp/Runtime.cpp

Lines changed: 3 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#include <console/Console.h>
2727
#include "sys/system_properties.h"
2828
#include "ManualInstrumentation.h"
29-
#include <snapshot_blob.h>
3029
#include "IsolateDisposer.h"
3130
#include <unistd.h>
3231
#include <thread>
@@ -186,15 +185,12 @@ void Runtime::Init(JNIEnv* env, jstring filesPath, jstring nativeLibDir, bool ve
186185

187186
Constants::APP_ROOT_FOLDER_PATH = filesRoot + "/app/";
188187
// read config options passed from Java
188+
// Indices correspond to positions in the com.tns.AppConfig.KnownKeys enum
189189
JniLocalRef v8Flags(env->GetObjectArrayElement(args, 0));
190190
Constants::V8_STARTUP_FLAGS = ArgConverter::jstringToString(v8Flags);
191191
JniLocalRef cacheCode(env->GetObjectArrayElement(args, 1));
192192
Constants::V8_CACHE_COMPILED_CODE = (bool) cacheCode;
193-
JniLocalRef snapshotScript(env->GetObjectArrayElement(args, 2));
194-
Constants::V8_HEAP_SNAPSHOT_SCRIPT = ArgConverter::jstringToString(snapshotScript);
195-
JniLocalRef snapshotBlob(env->GetObjectArrayElement(args, 3));
196-
Constants::V8_HEAP_SNAPSHOT_BLOB = ArgConverter::jstringToString(snapshotBlob);
197-
JniLocalRef profilerOutputDir(env->GetObjectArrayElement(args, 4));
193+
JniLocalRef profilerOutputDir(env->GetObjectArrayElement(args, 2));
198194

199195
DEBUG_WRITE("Initializing Telerik NativeScript");
200196

@@ -207,8 +203,6 @@ void Runtime::Init(JNIEnv* env, jstring filesPath, jstring nativeLibDir, bool ve
207203
Runtime::~Runtime() {
208204
delete this->m_objectManager;
209205
delete this->m_loopTimer;
210-
delete this->m_heapSnapshotBlob;
211-
delete this->m_startupData;
212206
CallbackHandlers::RemoveIsolateEntries(m_isolate);
213207
if (m_isMainThread) {
214208
if (m_mainLooper_fd[0] != -1) {
@@ -460,11 +454,6 @@ void Runtime::PassUncaughtExceptionFromWorkerToMainHandler(Local<v8::String> mes
460454
env.CallStaticVoidMethod(runtimeClass, mId, (jstring) jMsgLocal, (jstring) jfileNameLocal, (jstring) stTrace, lineno);
461455
}
462456

463-
void Runtime::ClearStartupData(JNIEnv* env, jobject obj) {
464-
delete m_heapSnapshotBlob;
465-
delete m_startupData;
466-
}
467-
468457
static void InitializeV8() {
469458
Runtime::platform = v8::platform::NewDefaultPlatform().release();
470459
V8::InitializePlatform(Runtime::platform);
@@ -475,117 +464,14 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
475464
tns::instrumentation::Frame frame("Runtime.PrepareV8Runtime");
476465

477466
Isolate::CreateParams create_params;
478-
bool didInitializeV8 = false;
479467

480468
create_params.array_buffer_allocator = &g_allocator;
481469

482-
m_startupData = new StartupData();
483-
484-
void* snapshotPtr = nullptr;
485-
string snapshotPath;
486-
bool snapshotPathExists = false;
487-
488-
// If device isn't running on Sdk 17
489-
if (m_androidVersion != 17) {
490-
snapshotPath = "libsnapshot.so";
491-
} else {
492-
// If device is running on android Sdk 17
493-
// dlopen reads relative path to dynamic libraries or reads from folder different than the nativeLibsDirs on the android device
494-
snapshotPath = nativeLibDir + "/libsnapshot.so";
495-
}
496-
497-
snapshotPtr = dlopen(snapshotPath.c_str(), RTLD_LAZY | RTLD_LOCAL);
498-
if (snapshotPtr == nullptr) {
499-
auto ignoredSearchValue = string("library \"" + snapshotPath + "\" not found");
500-
auto currentError = dlerror();
501-
std::string stringError(currentError);
502-
if (stringError.find(ignoredSearchValue) == std::string::npos) {
503-
DEBUG_WRITE_FORCE("Failed to load snapshot: %s", currentError);
504-
}
505-
}
506-
507-
bool isCustomSnapshotFound = false;
508-
if (snapshotPtr) {
509-
m_startupData->data = static_cast<const char*>(dlsym(snapshotPtr, "TNSSnapshot_blob"));
510-
m_startupData->raw_size = *static_cast<const unsigned int*>(dlsym(snapshotPtr, "TNSSnapshot_blob_len"));
511-
V8::SetSnapshotDataBlob(m_startupData);
512-
isCustomSnapshotFound = true;
513-
DEBUG_WRITE_FORCE("Snapshot library read %p (%dB).", m_startupData->data, m_startupData->raw_size);
514-
} else if (!Constants::V8_HEAP_SNAPSHOT_BLOB.empty() || !Constants::V8_HEAP_SNAPSHOT_SCRIPT.empty()) {
515-
DEBUG_WRITE_FORCE("Snapshot enabled.");
516-
517-
bool saveSnapshot = true;
518-
// we have a precompiled snapshot blob provided - try to load it directly
519-
if (!Constants::V8_HEAP_SNAPSHOT_BLOB.empty()) {
520-
snapshotPath = Constants::V8_HEAP_SNAPSHOT_BLOB;
521-
snapshotPathExists = File::Exists(snapshotPath);
522-
saveSnapshot = false;
523-
} else {
524-
std::string oldSnapshotBlobPath = filesPath + "/internal/snapshot.blob";
525-
std::string snapshotBlobPath = filesPath + "/internal/TNSSnapshot.blob";
526-
527-
bool oldSnapshotExists = File::Exists(oldSnapshotBlobPath);
528-
bool snapshotExists = File::Exists(snapshotBlobPath);
529-
530-
snapshotPathExists = oldSnapshotExists || snapshotExists;
531-
snapshotPath = oldSnapshotExists ? oldSnapshotBlobPath : snapshotBlobPath;
532-
}
533-
534-
if (snapshotPathExists) {
535-
m_heapSnapshotBlob = new MemoryMappedFile(MemoryMappedFile::Open(snapshotPath.c_str()));
536-
m_startupData->data = static_cast<const char*>(m_heapSnapshotBlob->memory);
537-
m_startupData->raw_size = m_heapSnapshotBlob->size;
538-
V8::SetSnapshotDataBlob(m_startupData);
539-
isCustomSnapshotFound = true;
540-
DEBUG_WRITE_FORCE("Snapshot read %s (%zuB).", snapshotPath.c_str(), m_heapSnapshotBlob->size);
541-
} else if (!saveSnapshot) {
542-
throw NativeScriptException("No snapshot file found at: " + snapshotPath);
543-
} else {
544-
InitializeV8();
545-
didInitializeV8 = true;
546-
547-
string customScript;
548-
549-
// check for custom script to include in the snapshot
550-
if (!Constants::V8_HEAP_SNAPSHOT_SCRIPT.empty() && File::Exists(Constants::V8_HEAP_SNAPSHOT_SCRIPT)) {
551-
customScript = ReadFileText(Constants::V8_HEAP_SNAPSHOT_SCRIPT);
552-
}
553-
554-
DEBUG_WRITE_FORCE("Creating heap snapshot");
555-
*m_startupData = Runtime::CreateSnapshotDataBlob(customScript.c_str());
556-
557-
if (m_startupData->raw_size == 0) {
558-
DEBUG_WRITE_FORCE("Failed to create heap snapshot.");
559-
} else {
560-
bool writeSuccess = File::WriteBinary(snapshotPath, m_startupData->data, m_startupData->raw_size);
561-
562-
if (!writeSuccess) {
563-
DEBUG_WRITE_FORCE("Failed to save created snapshot.");
564-
} else {
565-
DEBUG_WRITE_FORCE("Saved snapshot of %s (%zuB) in %s (%dB)",
566-
Constants::V8_HEAP_SNAPSHOT_SCRIPT.c_str(), customScript.size(),
567-
snapshotPath.c_str(), m_startupData->raw_size);
568-
}
569-
}
570-
571-
V8::SetSnapshotDataBlob(m_startupData);
572-
isCustomSnapshotFound = true;
573-
}
574-
}
575-
576-
if (!isCustomSnapshotFound) {
577-
// Load V8's built-in snapshot
578-
auto* snapshotBlobStartupData = new StartupData();
579-
snapshotBlobStartupData->data = reinterpret_cast<const char*>(&snapshot_blob_bin[0]);
580-
snapshotBlobStartupData->raw_size = snapshot_blob_bin_len;
581-
V8::SetSnapshotDataBlob(snapshotBlobStartupData);
582-
}
583-
584470
/*
585471
* Setup the V8Platform only once per process - once for the application lifetime
586472
* Don't execute again if main thread has already been initialized
587473
*/
588-
if (!didInitializeV8 && !s_mainThreadInitialized) {
474+
if (!s_mainThreadInitialized) {
589475
InitializeV8();
590476
}
591477

@@ -782,60 +668,6 @@ void Runtime::SetManualInstrumentationMode(jstring mode) {
782668
}
783669
}
784670

785-
StartupData Runtime::CreateSnapshotDataBlob(const char* embedded_source) {
786-
// Create a new isolate and a new context from scratch, optionally run
787-
// a script to embed, and serialize to create a snapshot blob.
788-
StartupData result = {nullptr, 0};
789-
{
790-
SnapshotCreator snapshot_creator;
791-
Isolate* isolate = snapshot_creator.GetIsolate();
792-
{
793-
HandleScope scope(isolate);
794-
Local<Context> context = Context::New(isolate);
795-
if (embedded_source != nullptr &&
796-
!Runtime::RunExtraCode(isolate, context, embedded_source, "<embedded>")) {
797-
return result;
798-
}
799-
snapshot_creator.SetDefaultContext(context);
800-
}
801-
result = snapshot_creator.CreateBlob(
802-
SnapshotCreator::FunctionCodeHandling::kClear);
803-
}
804-
805-
return result;
806-
}
807-
808-
bool Runtime::RunExtraCode(Isolate* isolate, Local<Context> context, const char* utf8_source, const char* name) {
809-
Context::Scope context_scope(context);
810-
TryCatch try_catch(isolate);
811-
Local<v8::String> source_string;
812-
if (!v8::String::NewFromUtf8(isolate, utf8_source, NewStringType::kNormal).ToLocal(&source_string)) {
813-
return false;
814-
}
815-
Local<v8::String> resource_name = v8::String::NewFromUtf8(isolate, name, NewStringType::kNormal).ToLocalChecked();
816-
ScriptOrigin origin(isolate, resource_name);
817-
ScriptCompiler::Source source(source_string, origin);
818-
Local<Script> script;
819-
if (!ScriptCompiler::Compile(context, &source).ToLocal(&script)) {
820-
DEBUG_WRITE_FORCE("# Script compile failed in %s@%d:%d\n%s\n",
821-
*v8::String::Utf8Value(isolate, try_catch.Message()->GetScriptResourceName()),
822-
try_catch.Message()->GetLineNumber(context).FromJust(),
823-
try_catch.Message()->GetStartColumn(context).FromJust(),
824-
*v8::String::Utf8Value(isolate, try_catch.Exception()));
825-
return false;
826-
}
827-
if (script->Run(context).IsEmpty()) {
828-
DEBUG_WRITE_FORCE("# Script run failed in %s@%d:%d\n%s\n",
829-
*v8::String::Utf8Value(isolate, try_catch.Message()->GetScriptResourceName()),
830-
try_catch.Message()->GetLineNumber(context).FromJust(),
831-
try_catch.Message()->GetStartColumn(context).FromJust(),
832-
*v8::String::Utf8Value(isolate, try_catch.Exception()));
833-
return false;
834-
}
835-
// CHECK(!try_catch.HasCaught());
836-
return true;
837-
}
838-
839671
void Runtime::DestroyRuntime() {
840672
s_id2RuntimeCache.erase(m_id);
841673
s_isolate2RuntimesCache.erase(m_isolate);

test-app/runtime/src/main/cpp/Runtime.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ class Runtime {
6060
bool TryCallGC();
6161
void PassExceptionToJsNative(JNIEnv* env, jobject obj, jthrowable exception, jstring message, jstring fullStackTrace, jstring jsStackTrace, jboolean isDiscarded);
6262
void PassUncaughtExceptionFromWorkerToMainHandler(v8::Local<v8::String> message, v8::Local<v8::String> stackTrace, v8::Local<v8::String> filename, int lineno);
63-
void ClearStartupData(JNIEnv* env, jobject obj);
6463
void DestroyRuntime();
6564

6665
void Lock();
@@ -101,9 +100,6 @@ class Runtime {
101100

102101
MessageLoopTimer* m_loopTimer;
103102

104-
v8::StartupData* m_startupData = nullptr;
105-
MemoryMappedFile* m_heapSnapshotBlob = nullptr;
106-
107103
int64_t m_lastUsedMemory;
108104

109105
v8::Persistent<v8::Function>* m_gcFunc;
@@ -115,8 +111,6 @@ class Runtime {
115111

116112
v8::Isolate* PrepareV8Runtime(const std::string& filesPath, const std::string& nativeLibsDir, const std::string& packageName, bool isDebuggable, const std::string& callingDir, const std::string& profilerOutputDir, const int maxLogcatObjectSize, const bool forceLog);
117113
jobject ConvertJsValueToJavaObject(JEnv& env, const v8::Local<v8::Value>& value, int classReturnType);
118-
static v8::StartupData CreateSnapshotDataBlob(const char* embedded_source);
119-
static bool RunExtraCode(v8::Isolate* isolate, v8::Local<v8::Context> context, const char* utf8_source, const char* name);
120114
static int GetAndroidVersion();
121115
static int m_androidVersion;
122116

test-app/runtime/src/main/cpp/com_tns_Runtime.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -288,15 +288,6 @@ extern "C" JNIEXPORT void Java_com_tns_Runtime_passExceptionToJsNative(JNIEnv* e
288288
}
289289
}
290290

291-
extern "C" JNIEXPORT void Java_com_tns_Runtime_clearStartupData(JNIEnv* env, jobject obj, jint runtimeId) {
292-
auto runtime = TryGetRuntime(runtimeId);
293-
if (runtime == nullptr) {
294-
return;
295-
}
296-
297-
runtime->ClearStartupData(env, obj);
298-
}
299-
300291
extern "C" JNIEXPORT jint Java_com_tns_Runtime_getPointerSize(JNIEnv* env, jobject obj) {
301292
return sizeof(void*);
302293
}

0 commit comments

Comments
 (0)