Commit a1b431d7 authored by Yang Guo's avatar Yang Guo Committed by Commit Bot

[serializer] share class positions tuple across contexts

Class positions is a struct that stores the start and end positions of a class
literal. It is stored both on class objects, and the template used to
instantiate class objects.

The template is reachable from the bytecode array and therefore serialized by
the startup serializer. Class objects are context-dependent and therefore
serialized by the partial serializer. Serializing class positions from both
serializers violates the assumption that we don't serialize any object twice.

R=gsathya@chromium.org

Bug: v8:8761
Change-Id: If22c554cc7396d63998a015454ce0c67a7d2e05c
Reviewed-on: https://chromium-review.googlesource.com/c/1444956Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59292}
parent 0b2fa277
......@@ -342,6 +342,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case ALIASED_ARGUMENTS_ENTRY_TYPE:
case PROMISE_CAPABILITY_TYPE:
case PROMISE_REACTION_TYPE:
case CLASS_POSITIONS_TYPE:
case DEBUG_INFO_TYPE:
case STACK_FRAME_INFO_TYPE:
case SMALL_ORDERED_HASH_MAP_TYPE:
......
......@@ -3806,6 +3806,14 @@ Handle<String> Factory::NumberToString(Smi number, bool check_cache) {
check_cache);
}
Handle<ClassPositions> Factory::NewClassPositions(int start, int end) {
Handle<ClassPositions> class_positions =
Handle<ClassPositions>::cast(NewStruct(CLASS_POSITIONS_TYPE, TENURED));
class_positions->set_start(start);
class_positions->set_end(end);
return class_positions;
}
Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
DCHECK(!shared->HasDebugInfo());
Heap* heap = isolate()->heap();
......
......@@ -892,6 +892,7 @@ class V8_EXPORT_PRIVATE Factory {
MessageTemplate message, Handle<Object> argument, int start_position,
int end_position, Handle<Script> script, Handle<Object> stack_frames);
Handle<ClassPositions> NewClassPositions(int start, int end);
Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared);
Handle<CoverageInfo> NewCoverageInfo(const ZoneVector<SourceRange>& slots);
......
......@@ -1809,6 +1809,12 @@ void Tuple3::Tuple3Verify(Isolate* isolate) {
VerifyObjectField(isolate, kValue3Offset);
}
void ClassPositions::ClassPositionsVerify(Isolate* isolate) {
CHECK(IsClassPositions());
VerifySmiField(kStartOffset);
VerifySmiField(kEndOffset);
}
void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify(
Isolate* isolate) {
CHECK(IsObjectBoilerplateDescription());
......
......@@ -98,6 +98,7 @@ namespace internal {
V(ALLOCATION_MEMENTO_TYPE) \
V(ASM_WASM_DATA_TYPE) \
V(ASYNC_GENERATOR_REQUEST_TYPE) \
V(CLASS_POSITIONS_TYPE) \
V(DEBUG_INFO_TYPE) \
V(FUNCTION_TEMPLATE_INFO_TYPE) \
V(FUNCTION_TEMPLATE_RARE_DATA_TYPE) \
......@@ -321,6 +322,7 @@ namespace internal {
V(_, ASM_WASM_DATA_TYPE, AsmWasmData, asm_wasm_data) \
V(_, ASYNC_GENERATOR_REQUEST_TYPE, AsyncGeneratorRequest, \
async_generator_request) \
V(_, CLASS_POSITIONS_TYPE, ClassPositions, class_positions) \
V(_, DEBUG_INFO_TYPE, DebugInfo, debug_info) \
V(_, FUNCTION_TEMPLATE_INFO_TYPE, FunctionTemplateInfo, \
function_template_info) \
......
......@@ -1744,6 +1744,13 @@ void Tuple3::Tuple3Print(std::ostream& os) { // NOLINT
os << "\n";
}
void ClassPositions::ClassPositionsPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "ClassPositions");
os << "\n - start position: " << start();
os << "\n - end position: " << end();
os << "\n";
}
void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint(
std::ostream& os) { // NOLINT
PrintHeader(os, "ArrayBoilerplateDescription");
......
......@@ -3146,6 +3146,10 @@ void Tuple3::BriefPrintDetails(std::ostream& os) {
<< Brief(value3());
}
void ClassPositions::BriefPrintDetails(std::ostream& os) {
os << " " << start() << ", " << end();
}
void ArrayBoilerplateDescription::BriefPrintDetails(std::ostream& os) {
os << " " << elements_kind() << ", " << Brief(constant_elements());
}
......@@ -9436,10 +9440,11 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
// Check if we should print {function} as a class.
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsTuple2()) {
Tuple2 class_positions = Tuple2::cast(*maybe_class_positions);
int start_position = Smi::ToInt(class_positions->value1());
int end_position = Smi::ToInt(class_positions->value2());
if (maybe_class_positions->IsClassPositions()) {
ClassPositions class_positions =
ClassPositions::cast(*maybe_class_positions);
int start_position = class_positions->start();
int end_position = class_positions->end();
Handle<String> script_source(
String::cast(Script::cast(shared_info->script())->source()), isolate);
return isolate->factory()->NewSubString(script_source, start_position,
......
......@@ -171,6 +171,7 @@ enum InstanceType : uint16_t {
ALLOCATION_MEMENTO_TYPE,
ASM_WASM_DATA_TYPE,
ASYNC_GENERATOR_REQUEST_TYPE,
CLASS_POSITIONS_TYPE,
DEBUG_INFO_TYPE,
FUNCTION_TEMPLATE_INFO_TYPE,
FUNCTION_TEMPLATE_RARE_DATA_TYPE,
......
......@@ -493,10 +493,8 @@ Handle<ClassBoilerplate> ClassBoilerplate::BuildClassBoilerplate(
attribs);
}
{
Handle<Smi> start_position(Smi::FromInt(expr->start_position()), isolate);
Handle<Smi> end_position(Smi::FromInt(expr->end_position()), isolate);
Handle<Tuple2> class_positions =
factory->NewTuple2(start_position, end_position, NOT_TENURED);
Handle<ClassPositions> class_positions = factory->NewClassPositions(
expr->start_position(), expr->end_position());
static_desc.AddConstant(isolate, factory->class_positions_symbol(),
class_positions, DONT_ENUM);
}
......
......@@ -24,11 +24,15 @@ Tuple2::Tuple2(Address ptr) : Struct(ptr) {}
Tuple3::Tuple3(Address ptr) : Tuple2(ptr) {}
OBJECT_CONSTRUCTORS_IMPL(AccessorPair, Struct)
OBJECT_CONSTRUCTORS_IMPL(ClassPositions, Struct)
CAST_ACCESSOR(AccessorPair)
CAST_ACCESSOR(Struct)
CAST_ACCESSOR(Tuple2)
CAST_ACCESSOR(Tuple3)
CAST_ACCESSOR(ClassPositions)
void Struct::InitializeBody(int object_size) {
Object value = GetReadOnlyRoots().undefined_value();
for (int offset = kHeaderSize; offset < object_size; offset += kPointerSize) {
......@@ -43,6 +47,9 @@ ACCESSORS(Tuple3, value3, Object, kValue3Offset)
ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
SMI_ACCESSORS(ClassPositions, start, kStartOffset)
SMI_ACCESSORS(ClassPositions, end, kEndOffset)
Object AccessorPair::get(AccessorComponent component) {
return component == ACCESSOR_GETTER ? getter() : setter();
}
......
......@@ -119,6 +119,31 @@ class AccessorPair : public Struct {
OBJECT_CONSTRUCTORS(AccessorPair, Struct);
};
class ClassPositions : public Struct {
public:
DECL_INT_ACCESSORS(start)
DECL_INT_ACCESSORS(end)
DECL_CAST(ClassPositions)
// Dispatched behavior.
DECL_PRINTER(ClassPositions)
DECL_VERIFIER(ClassPositions)
void BriefPrintDetails(std::ostream& os);
// Layout description.
#define CLASS_POSITIONS_FIELDS(V) \
V(kStartOffset, kTaggedSize) \
V(kEndOffset, kTaggedSize) \
/* Total size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, CLASS_POSITIONS_FIELDS)
#undef CLASS_POSITIONS_FIELDS
OBJECT_CONSTRUCTORS(ClassPositions, Struct);
};
} // namespace internal
} // namespace v8
......
......@@ -133,7 +133,7 @@ bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject o) {
DCHECK(!o->IsScript());
return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() ||
o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() ||
o->IsTemplateInfo() ||
o->IsTemplateInfo() || o->IsClassPositions() ||
o->map() == ReadOnlyRoots(startup_serializer_->isolate())
.fixed_cow_array_map();
}
......
......@@ -3923,5 +3923,27 @@ TEST(CachedCompileFunctionInContext) {
}
}
TEST(SnapshotCreatorAnonClassWithKeep) {
DisableAlwaysOpt();
v8::SnapshotCreator creator;
v8::Isolate* isolate = creator.GetIsolate();
{
v8::HandleScope handle_scope(isolate);
{
v8::Local<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
CompileRun(
"function Foo() { return class {}; } \n"
"class Bar extends Foo() {}\n"
"Foo()\n");
creator.SetDefaultContext(context);
}
}
v8::StartupData blob =
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kKeep);
delete[] blob.data;
}
} // namespace internal
} // namespace v8
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment