Skip to content

Commit d915b8d

Browse files
mmarchiniCommit Bot
authored andcommitted
[snapshot] Fix copy-IET integration with Code Cache
[email protected], [email protected], [email protected] Bug: v8:9122 Change-Id: I6336d2fc0249269a749d99dcae7c172b2ccaac75 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1570582 Reviewed-by: Jakob Gruber <[email protected]> Commit-Queue: Jakob Gruber <[email protected]> Cr-Commit-Position: refs/heads/master@{#60937}
1 parent 2d00edf commit d915b8d

File tree

4 files changed

+141
-3
lines changed

4 files changed

+141
-3
lines changed

src/snapshot/code-serializer.cc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ void CodeSerializer::SerializeObject(HeapObject obj) {
187187
return;
188188
}
189189

190+
// NOTE(mmarchini): If we try to serialize an InterpreterData our process
191+
// will crash since it stores a code object. Instead, we serialize the
192+
// bytecode array stored within the InterpreterData, which is the important
193+
// information. On deserialization we'll create our code objects again, if
194+
// --interpreted-frames-native-stack is on. See v8:9122 for more context
195+
#ifndef V8_TARGET_ARCH_ARM
196+
if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack) &&
197+
obj->IsInterpreterData()) {
198+
obj = InterpreterData::cast(obj)->bytecode_array();
199+
}
200+
#endif // V8_TARGET_ARCH_ARM
201+
190202
if (obj->IsBytecodeArray()) {
191203
// Clear the stack frame cache if present
192204
BytecodeArray::cast(obj)->ClearFrameCacheFromSourcePositionTable();
@@ -210,6 +222,48 @@ void CodeSerializer::SerializeGeneric(HeapObject heap_object) {
210222
serializer.Serialize();
211223
}
212224

225+
#ifndef V8_TARGET_ARCH_ARM
226+
// NOTE(mmarchini): when FLAG_interpreted_frames_native_stack is on, we want to
227+
// create duplicates of InterpreterEntryTrampoline for the deserialized
228+
// functions, otherwise we'll call the builtin IET for those functions (which
229+
// is not what a user of this flag wants).
230+
void CreateInterpreterDataForDeserializedCode(Isolate* isolate,
231+
Handle<SharedFunctionInfo> sfi,
232+
bool log_code_creation) {
233+
Script script = Script::cast(sfi->script());
234+
Handle<Script> script_handle(script, isolate);
235+
String name = ReadOnlyRoots(isolate).empty_string();
236+
if (script->name()->IsString()) name = String::cast(script->name());
237+
Handle<String> name_handle(name, isolate);
238+
239+
SharedFunctionInfo::ScriptIterator iter(isolate, script);
240+
for (SharedFunctionInfo info = iter.Next(); !info.is_null();
241+
info = iter.Next()) {
242+
if (!info->HasBytecodeArray()) continue;
243+
Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
244+
isolate->factory()->interpreter_entry_trampoline_for_profiling()));
245+
246+
Handle<InterpreterData> interpreter_data =
247+
Handle<InterpreterData>::cast(isolate->factory()->NewStruct(
248+
INTERPRETER_DATA_TYPE, AllocationType::kOld));
249+
250+
interpreter_data->set_bytecode_array(info->GetBytecodeArray());
251+
interpreter_data->set_interpreter_trampoline(*code);
252+
253+
info->set_interpreter_data(*interpreter_data);
254+
255+
if (!log_code_creation) continue;
256+
Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
257+
int line_num = script->GetLineNumber(info->StartPosition()) + 1;
258+
int column_num = script->GetColumnNumber(info->StartPosition()) + 1;
259+
PROFILE(isolate,
260+
CodeCreateEvent(CodeEventListener::INTERPRETED_FUNCTION_TAG,
261+
*abstract_code, info, *name_handle, line_num,
262+
column_num));
263+
}
264+
}
265+
#endif // V8_TARGET_ARCH_ARM
266+
213267
MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
214268
Isolate* isolate, ScriptData* cached_data, Handle<String> source,
215269
ScriptOriginOptions origin_options) {
@@ -253,6 +307,13 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
253307
isolate->logger()->is_listening_to_code_events() ||
254308
isolate->is_profiling() ||
255309
isolate->code_event_dispatcher()->IsListeningToCodeEvents();
310+
311+
#ifndef V8_TARGET_ARCH_ARM
312+
if (V8_UNLIKELY(FLAG_interpreted_frames_native_stack))
313+
CreateInterpreterDataForDeserializedCode(isolate, result,
314+
log_code_creation);
315+
#endif // V8_TARGET_ARCH_ARM
316+
256317
if (log_code_creation || FLAG_log_function_events) {
257318
String name = ReadOnlyRoots(isolate).empty_string();
258319
Script script = Script::cast(result->script());

test/cctest/cctest.status

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,9 @@
567567
# allocation. Fix logging to work without feedback vectors and enable these
568568
# tests in lite_mode.
569569
'test-log/ExternalCodeEventListenerWithInterpretedFramesNativeStack': [SKIP],
570-
'test-log/LogInterpretedFramesNativeStack': [SKIP]
570+
'test-log/LogInterpretedFramesNativeStack': [SKIP],
571+
'test-log/LogInterpretedFramesNativeStackWithSerialization': [SKIP],
572+
'test-serialize/CodeSerializerOnePlusOneWithInterpretedFramesNativeStack': [SKIP]
571573
}], # lite_mode
572574

573575
##############################################################################
@@ -606,6 +608,8 @@
606608
# --interpreted-frames-native-stack tests
607609
'test-log/ExternalCodeEventListenerWithInterpretedFramesNativeStack': [SKIP],
608610
'test-log/LogInterpretedFramesNativeStack': [SKIP],
611+
'test-log/LogInterpretedFramesNativeStackWithSerialization': [SKIP],
612+
'test-serialize/CodeSerializerOnePlusOneWithInterpretedFramesNativeStack': [SKIP],
609613

610614
# Crashes on native arm.
611615
'test-macro-assembler-arm/ExtractLane': [PASS, ['arch == arm and not simulator_run', SKIP]],

test/cctest/test-log.cc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <vector>
3232
#include "src/api-inl.h"
3333
#include "src/builtins/builtins.h"
34+
#include "src/compilation-cache.h"
3435
#include "src/log-utils.h"
3536
#include "src/log.h"
3637
#include "src/objects-inl.h"
@@ -660,6 +661,68 @@ UNINITIALIZED_TEST(LogInterpretedFramesNativeStack) {
660661
}
661662
isolate->Dispose();
662663
}
664+
665+
UNINITIALIZED_TEST(LogInterpretedFramesNativeStackWithSerialization) {
666+
SETUP_FLAGS();
667+
i::FLAG_interpreted_frames_native_stack = true;
668+
i::FLAG_always_opt = false;
669+
v8::Isolate::CreateParams create_params;
670+
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
671+
672+
v8::ScriptCompiler::CachedData* cache = nullptr;
673+
674+
bool has_cache = cache != nullptr;
675+
// NOTE(mmarchini): Runs the test two times. The first time it will compile
676+
// our script and will create a code cache for it. The second time we'll
677+
// deserialize the cache and check if our function was logged correctly.
678+
// We disallow compilation on the second run to ensure we're loading from
679+
// cache.
680+
do {
681+
v8::Isolate* isolate = v8::Isolate::New(create_params);
682+
683+
{
684+
ScopedLoggerInitializer logger(saved_log, saved_prof, isolate);
685+
686+
has_cache = cache != nullptr;
687+
v8::ScriptCompiler::CompileOptions options =
688+
has_cache ? v8::ScriptCompiler::kConsumeCodeCache
689+
: v8::ScriptCompiler::kEagerCompile;
690+
691+
v8::HandleScope scope(isolate);
692+
v8::Isolate::Scope isolate_scope(isolate);
693+
v8::Local<v8::Context> context = v8::Context::New(isolate);
694+
v8::Local<v8::String> source = v8_str(
695+
"function eyecatcher() { return a * a; } return eyecatcher();");
696+
v8::Local<v8::String> arg_str = v8_str("a");
697+
v8::ScriptOrigin origin(v8_str("filename"));
698+
699+
i::DisallowCompilation* no_compile_expected =
700+
has_cache ? new i::DisallowCompilation(
701+
reinterpret_cast<i::Isolate*>(isolate))
702+
: nullptr;
703+
704+
v8::ScriptCompiler::Source script_source(source, origin, cache);
705+
v8::Local<v8::Function> fun =
706+
v8::ScriptCompiler::CompileFunctionInContext(
707+
context, &script_source, 1, &arg_str, 0, nullptr, options)
708+
.ToLocalChecked();
709+
if (has_cache) {
710+
logger.StopLogging();
711+
CHECK(logger.ContainsLine({"InterpretedFunction", "eyecatcher"}));
712+
}
713+
v8::Local<v8::Value> arg = v8_num(3);
714+
v8::Local<v8::Value> result =
715+
fun->Call(context, v8::Undefined(isolate), 1, &arg).ToLocalChecked();
716+
CHECK_EQ(9, result->Int32Value(context).FromJust());
717+
cache = v8::ScriptCompiler::CreateCodeCacheForFunction(fun);
718+
719+
if (no_compile_expected != nullptr) delete no_compile_expected;
720+
}
721+
722+
isolate->Dispose();
723+
} while (!has_cache);
724+
delete cache;
725+
}
663726
#endif // V8_TARGET_ARCH_ARM
664727

665728
UNINITIALIZED_TEST(ExternalCodeEventListener) {

test/cctest/test-serialize.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,7 +1616,7 @@ static Handle<SharedFunctionInfo> CompileScriptAndProduceCache(
16161616
return sfi;
16171617
}
16181618

1619-
void TestCodeSerializerOnePlusOneImpl() {
1619+
void TestCodeSerializerOnePlusOneImpl(bool verify_builtins_count = true) {
16201620
LocalContext context;
16211621
Isolate* isolate = CcTest::i_isolate();
16221622
isolate->compilation_cache()->Disable(); // Disable same-isolate code cache.
@@ -1660,13 +1660,23 @@ void TestCodeSerializerOnePlusOneImpl() {
16601660
Execution::Call(isolate, copy_fun, global, 0, nullptr).ToHandleChecked();
16611661
CHECK_EQ(2, Handle<Smi>::cast(copy_result)->value());
16621662

1663-
CHECK_EQ(builtins_count, CountBuiltins());
1663+
if (verify_builtins_count) CHECK_EQ(builtins_count, CountBuiltins());
16641664

16651665
delete cache;
16661666
}
16671667

16681668
TEST(CodeSerializerOnePlusOne) { TestCodeSerializerOnePlusOneImpl(); }
16691669

1670+
// See bug v8:9122
1671+
#ifndef V8_TARGET_ARCH_ARM
1672+
TEST(CodeSerializerOnePlusOneWithInterpretedFramesNativeStack) {
1673+
FLAG_interpreted_frames_native_stack = true;
1674+
// We pass false because this test will create IET copies (which are
1675+
// builtins).
1676+
TestCodeSerializerOnePlusOneImpl(false);
1677+
}
1678+
#endif
1679+
16701680
TEST(CodeSerializerOnePlusOneWithDebugger) {
16711681
v8::HandleScope scope(CcTest::isolate());
16721682
static v8::debug::DebugDelegate dummy_delegate;

0 commit comments

Comments
 (0)