Commit 7478c5a0 authored by mvstanton's avatar mvstanton Committed by Commit bot

Feedback vector: ASAN found memory leaks during AST Numbering pass.

The cause was dynamic allocation of an accounting structure used to
create/initialize the type feedback vector, done at the end of the
numbering pass. The solution is to Zone-allocate the structure to
bring it's lifetime in line with the compilation unit.

BUG=

Review URL: https://codereview.chromium.org/1014793003

Cr-Commit-Position: refs/heads/master@{#27241}
parent 7f7cff33
......@@ -17,6 +17,7 @@ class AstNumberingVisitor FINAL : public AstVisitor {
explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
: AstVisitor(),
next_id_(BailoutId::FirstUsable().ToInt()),
properties_(zone),
ic_slot_cache_(FLAG_vector_ics ? 4 : 0),
dont_optimize_reason_(kNoReason) {
InitializeAstVisitor(isolate, zone);
......
......@@ -188,7 +188,7 @@ class AstProperties FINAL BASE_EMBEDDED {
public:
class Flags : public EnumSet<AstPropertiesFlag, int> {};
AstProperties() : node_count_(0) {}
explicit AstProperties(Zone* zone) : node_count_(0), spec_(zone) {}
Flags* flags() { return &flags_; }
int node_count() { return node_count_; }
......@@ -200,12 +200,12 @@ class AstProperties FINAL BASE_EMBEDDED {
int ic_slots() const { return spec_.ic_slots(); }
void increase_ic_slots(int count) { spec_.increase_ic_slots(count); }
void SetKind(int ic_slot, Code::Kind kind) { spec_.SetKind(ic_slot, kind); }
const FeedbackVectorSpec& get_spec() const { return spec_; }
const ZoneFeedbackVectorSpec* get_spec() const { return &spec_; }
private:
Flags flags_;
int node_count_;
FeedbackVectorSpec spec_;
ZoneFeedbackVectorSpec spec_;
};
......@@ -2555,7 +2555,7 @@ class FunctionLiteral FINAL : public Expression {
void set_ast_properties(AstProperties* ast_properties) {
ast_properties_ = *ast_properties;
}
const FeedbackVectorSpec& feedback_vector_spec() const {
const ZoneFeedbackVectorSpec* feedback_vector_spec() const {
return ast_properties_.get_spec();
}
bool dont_optimize() { return dont_optimize_reason_ != kNoReason; }
......@@ -2579,6 +2579,7 @@ class FunctionLiteral FINAL : public Expression {
scope_(scope),
body_(body),
raw_inferred_name_(ast_value_factory->empty_string()),
ast_properties_(zone),
dont_optimize_reason_(kNoReason),
materialized_literal_count_(materialized_literal_count),
expected_property_count_(expected_property_count),
......
......@@ -2143,10 +2143,9 @@ bool Genesis::InstallNatives() {
if (FLAG_vector_ics) {
// Apply embeds an IC, so we need a type vector of size 1 in the shared
// function info.
FeedbackVectorSpec spec(0, 1);
spec.SetKind(0, Code::CALL_IC);
FeedbackVectorSpec spec(0, Code::CALL_IC);
Handle<TypeFeedbackVector> feedback_vector =
factory()->NewTypeFeedbackVector(spec);
factory()->NewTypeFeedbackVector(&spec);
apply->shared()->set_feedback_vector(*feedback_vector);
}
......
......@@ -2007,9 +2007,14 @@ void Factory::BecomeJSFunction(Handle<JSProxy> proxy) {
}
Handle<TypeFeedbackVector> Factory::NewTypeFeedbackVector(
const FeedbackVectorSpec& spec) {
return TypeFeedbackVector::Allocate(isolate(), spec);
template Handle<TypeFeedbackVector> Factory::NewTypeFeedbackVector(
const ZoneFeedbackVectorSpec* spec);
template Handle<TypeFeedbackVector> Factory::NewTypeFeedbackVector(
const FeedbackVectorSpec* spec);
template <typename Spec>
Handle<TypeFeedbackVector> Factory::NewTypeFeedbackVector(const Spec* spec) {
return TypeFeedbackVector::Allocate<Spec>(isolate(), spec);
}
......@@ -2077,9 +2082,9 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_debug_info(*undefined_value(), SKIP_WRITE_BARRIER);
share->set_inferred_name(*empty_string(), SKIP_WRITE_BARRIER);
FeedbackVectorSpec empty_spec;
FeedbackVectorSpec empty_spec(0);
Handle<TypeFeedbackVector> feedback_vector =
NewTypeFeedbackVector(empty_spec);
NewTypeFeedbackVector(&empty_spec);
share->set_feedback_vector(*feedback_vector, SKIP_WRITE_BARRIER);
#if TRACE_MAPS
share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
......
......@@ -616,8 +616,8 @@ class Factory FINAL {
MaybeHandle<Code> code);
// Allocate a new type feedback vector
Handle<TypeFeedbackVector> NewTypeFeedbackVector(
const FeedbackVectorSpec& spec);
template <typename Spec>
Handle<TypeFeedbackVector> NewTypeFeedbackVector(const Spec* spec);
// Allocates a new JSMessageObject object.
Handle<JSMessageObject> NewJSMessageObject(
......
......@@ -3124,10 +3124,9 @@ void Heap::CreateInitialObjects() {
set_microtask_queue(empty_fixed_array());
if (FLAG_vector_ics) {
FeedbackVectorSpec spec(0, 1);
spec.SetKind(0, Code::KEYED_LOAD_IC);
FeedbackVectorSpec spec(0, Code::KEYED_LOAD_IC);
Handle<TypeFeedbackVector> dummy_vector =
factory->NewTypeFeedbackVector(spec);
factory->NewTypeFeedbackVector(&spec);
dummy_vector->Set(FeedbackVectorICSlot(0),
*TypeFeedbackVector::MegamorphicSentinel(isolate()),
SKIP_WRITE_BARRIER);
......
......@@ -75,11 +75,18 @@ void TypeFeedbackVector::SetKind(FeedbackVectorICSlot slot, Code::Kind kind) {
}
template Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
Isolate* isolate, const FeedbackVectorSpec* spec);
template Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
Isolate* isolate, const ZoneFeedbackVectorSpec* spec);
// static
Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
Isolate* isolate, const FeedbackVectorSpec& spec) {
const int slot_count = spec.slots();
const int ic_slot_count = spec.ic_slots();
template <typename Spec>
Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate,
const Spec* spec) {
const int slot_count = spec->slots();
const int ic_slot_count = spec->ic_slots();
const int index_count =
FLAG_vector_ics ? VectorICComputer::word_count(ic_slot_count) : 0;
const int length = slot_count + (ic_slot_count * elements_per_ic_slot()) +
......@@ -113,7 +120,7 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(
Handle<TypeFeedbackVector> vector = Handle<TypeFeedbackVector>::cast(array);
if (FLAG_vector_ics) {
for (int i = 0; i < ic_slot_count; i++) {
vector->SetKind(FeedbackVectorICSlot(i), spec.GetKind(i));
vector->SetKind(FeedbackVectorICSlot(i), spec->GetKind(i));
}
}
return vector;
......
......@@ -12,18 +12,44 @@
#include "src/heap/heap.h"
#include "src/isolate.h"
#include "src/objects.h"
#include "src/zone-containers.h"
namespace v8 {
namespace internal {
class FeedbackVectorSpec {
public:
FeedbackVectorSpec() : slots_(0), ic_slots_(0) {}
FeedbackVectorSpec(int slots, int ic_slots)
: slots_(slots), ic_slots_(ic_slots) {
if (FLAG_vector_ics) ic_slot_kinds_.resize(ic_slots);
FeedbackVectorSpec() : slots_(0), has_ic_slot_(false) {}
explicit FeedbackVectorSpec(int slots) : slots_(slots), has_ic_slot_(false) {}
FeedbackVectorSpec(int slots, Code::Kind ic_slot_kind)
: slots_(slots), has_ic_slot_(true), ic_kind_(ic_slot_kind) {}
int slots() const { return slots_; }
int ic_slots() const { return has_ic_slot_ ? 1 : 0; }
Code::Kind GetKind(int ic_slot) const {
DCHECK(FLAG_vector_ics && has_ic_slot_ && ic_slot == 0);
return ic_kind_;
}
private:
int slots_;
bool has_ic_slot_;
Code::Kind ic_kind_;
};
class ZoneFeedbackVectorSpec {
public:
explicit ZoneFeedbackVectorSpec(Zone* zone)
: slots_(0), ic_slots_(0), ic_slot_kinds_(zone) {}
ZoneFeedbackVectorSpec(Zone* zone, int slots, int ic_slots)
: slots_(slots),
ic_slots_(ic_slots),
ic_slot_kinds_(FLAG_vector_ics ? ic_slots : 0, zone) {}
int slots() const { return slots_; }
void increase_slots(int count) { slots_ += count; }
......@@ -46,7 +72,7 @@ class FeedbackVectorSpec {
private:
int slots_;
int ic_slots_;
std::vector<unsigned char> ic_slot_kinds_;
ZoneVector<unsigned char> ic_slot_kinds_;
};
......@@ -161,8 +187,9 @@ class TypeFeedbackVector : public FixedArray {
// IC slots need metadata to recognize the type of IC.
Code::Kind GetKind(FeedbackVectorICSlot slot) const;
template <typename Spec>
static Handle<TypeFeedbackVector> Allocate(Isolate* isolate,
const FeedbackVectorSpec& spec);
const Spec* spec);
static Handle<TypeFeedbackVector> Copy(Isolate* isolate,
Handle<TypeFeedbackVector> vector);
......
......@@ -22,10 +22,11 @@ TEST(VectorStructure) {
v8::HandleScope scope(context->GetIsolate());
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Zone* zone = isolate->runtime_zone();
// Empty vectors are the empty fixed array.
FeedbackVectorSpec empty;
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(empty);
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&empty);
CHECK(Handle<FixedArray>::cast(vector)
.is_identical_to(factory->empty_fixed_array()));
// Which can nonetheless be queried.
......@@ -34,24 +35,21 @@ TEST(VectorStructure) {
CHECK_EQ(0, vector->Slots());
CHECK_EQ(0, vector->ICSlots());
FeedbackVectorSpec one_slot(1, 0);
vector = factory->NewTypeFeedbackVector(one_slot);
FeedbackVectorSpec one_slot(1);
vector = factory->NewTypeFeedbackVector(&one_slot);
CHECK_EQ(1, vector->Slots());
CHECK_EQ(0, vector->ICSlots());
FeedbackVectorSpec one_icslot(0, 1);
if (FLAG_vector_ics) {
one_icslot.SetKind(0, Code::CALL_IC);
}
vector = factory->NewTypeFeedbackVector(one_icslot);
FeedbackVectorSpec one_icslot(0, Code::CALL_IC);
vector = factory->NewTypeFeedbackVector(&one_icslot);
CHECK_EQ(0, vector->Slots());
CHECK_EQ(1, vector->ICSlots());
FeedbackVectorSpec spec(3, 5);
ZoneFeedbackVectorSpec spec(zone, 3, 5);
if (FLAG_vector_ics) {
for (int i = 0; i < 5; i++) spec.SetKind(i, Code::CALL_IC);
}
vector = factory->NewTypeFeedbackVector(spec);
vector = factory->NewTypeFeedbackVector(&spec);
CHECK_EQ(3, vector->Slots());
CHECK_EQ(5, vector->ICSlots());
......@@ -88,8 +86,9 @@ TEST(VectorICMetadata) {
}
Isolate* isolate = CcTest::i_isolate();
Factory* factory = isolate->factory();
Zone* zone = isolate->runtime_zone();
FeedbackVectorSpec spec(10, 3 * 10);
ZoneFeedbackVectorSpec spec(zone, 10, 3 * 10);
// Set metadata.
for (int i = 0; i < 30; i++) {
Code::Kind kind;
......@@ -103,7 +102,7 @@ TEST(VectorICMetadata) {
spec.SetKind(i, kind);
}
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(spec);
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
CHECK_EQ(10, vector->Slots());
CHECK_EQ(3 * 10, vector->ICSlots());
......@@ -136,8 +135,8 @@ TEST(VectorSlotClearing) {
// We only test clearing FeedbackVectorSlots, not FeedbackVectorICSlots.
// The reason is that FeedbackVectorICSlots need a full code environment
// to fully test (See VectorICProfilerStatistics test below).
FeedbackVectorSpec spec(5, 0);
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(spec);
FeedbackVectorSpec spec(5);
Handle<TypeFeedbackVector> vector = factory->NewTypeFeedbackVector(&spec);
// Fill with information
vector->Set(FeedbackVectorSlot(0), Smi::FromInt(1));
......
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