Commit fdc78d29 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ic] Cleanup vector-based IC clearing.

... and don't clear ICs during GC. The IC clearing used to prevent memory
leaks but it's not necessary anymore because all the handlers that need
to embed objects already use weak cells.

This CL unblocks inlining of IC dispatchers into bytecode handlers.

BUG=v8:5917

Change-Id: I229b9ba8dba44f431dfbe8ac5370d855e3e84dd6
Reviewed-on: https://chromium-review.googlesource.com/442127
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43209}
parent d0b90624
......@@ -257,21 +257,14 @@ void FeedbackVector::AddToCodeCoverageList(Isolate* isolate,
isolate->SetCodeCoverageList(*list);
}
// This logic is copied from
// StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget.
static bool ClearLogic(Isolate* isolate) {
return FLAG_cleanup_code_caches_at_gc && isolate->serializer_enabled();
}
void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
bool force_clear) {
void FeedbackVector::ClearSlots(JSFunction* host_function) {
Isolate* isolate = GetIsolate();
if (!force_clear && !ClearLogic(isolate)) return;
Object* uninitialized_sentinel =
FeedbackVector::RawUninitializedSentinel(isolate);
Oddball* undefined_value = isolate->heap()->undefined_value();
bool feedback_updated = false;
FeedbackMetadataIterator iter(metadata());
while (iter.HasNext()) {
FeedbackSlot slot = iter.Next();
......@@ -282,35 +275,53 @@ void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
switch (kind) {
case FeedbackSlotKind::kCall: {
CallICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kLoadProperty: {
LoadICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kLoadGlobalInsideTypeof:
case FeedbackSlotKind::kLoadGlobalNotInsideTypeof: {
LoadGlobalICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kLoadKeyed: {
KeyedLoadICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kStorePropertySloppy:
case FeedbackSlotKind::kStorePropertyStrict: {
StoreICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kStoreKeyedStrict: {
KeyedStoreICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kBinaryOp:
......@@ -332,17 +343,22 @@ void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
// regularly.
if (instance_type != ALLOCATION_SITE_TYPE) {
Set(slot, uninitialized_sentinel, SKIP_WRITE_BARRIER);
feedback_updated = true;
}
}
break;
}
case FeedbackSlotKind::kLiteral: {
Set(slot, undefined_value, SKIP_WRITE_BARRIER);
feedback_updated = true;
break;
}
case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
StoreDataPropertyInLiteralICNexus nexus(this, slot);
nexus.Clear(shared->code());
if (!nexus.IsCleared()) {
nexus.Clear();
feedback_updated = true;
}
break;
}
case FeedbackSlotKind::kToBoolean:
......@@ -353,6 +369,9 @@ void FeedbackVector::ClearSlotsImpl(SharedFunctionInfo* shared,
}
}
}
if (feedback_updated) {
IC::OnFeedbackChanged(isolate, host_function);
}
}
Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
......@@ -571,8 +590,6 @@ float CallICNexus::ComputeCallFrequency() {
return static_cast<float>(call_count / invocation_count);
}
void CallICNexus::Clear(Code* host) { CallIC::Clear(GetIsolate(), host, this); }
void CallICNexus::ConfigureUninitialized() {
Isolate* isolate = GetIsolate();
SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
......@@ -877,16 +894,6 @@ bool FeedbackNexus::FindHandlers(List<Handle<Object>>* code_list,
return count == length;
}
void LoadICNexus::Clear(Code* host) { LoadIC::Clear(GetIsolate(), host, this); }
void LoadGlobalICNexus::Clear(Code* host) {
LoadGlobalIC::Clear(GetIsolate(), host, this);
}
void KeyedLoadICNexus::Clear(Code* host) {
KeyedLoadIC::Clear(GetIsolate(), host, this);
}
Name* KeyedLoadICNexus::FindFirstName() const {
Object* feedback = GetFeedback();
if (IsPropertyNameFeedback(feedback)) {
......@@ -903,14 +910,6 @@ Name* KeyedStoreICNexus::FindFirstName() const {
return NULL;
}
void StoreICNexus::Clear(Code* host) {
StoreIC::Clear(GetIsolate(), host, this);
}
void KeyedStoreICNexus::Clear(Code* host) {
KeyedStoreIC::Clear(GetIsolate(), host, this);
}
KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
KeyedAccessStoreMode mode = STANDARD_STORE;
MapHandleList maps;
......
......@@ -332,11 +332,7 @@ class FeedbackVector : public FixedArray {
DECLARE_PRINTER(FeedbackVector)
// Clears the vector slots.
void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
ClearSlotsImpl(shared, false);
}
void ClearSlots(JSFunction* host_function);
// The object that indicates an uninitialized cache.
static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
......@@ -352,7 +348,6 @@ class FeedbackVector : public FixedArray {
static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
private:
void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
static void AddToCodeCoverageList(Isolate* isolate,
Handle<FeedbackVector> vector);
......@@ -453,6 +448,12 @@ class FeedbackNexus {
int length = -1) const;
virtual Name* FindFirstName() const { return NULL; }
bool IsCleared() {
InlineCacheState state = StateFromFeedback();
return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
}
virtual void Clear() { ConfigureUninitialized(); }
virtual void ConfigureUninitialized();
virtual void ConfigurePremonomorphic();
virtual void ConfigureMegamorphic();
......@@ -494,8 +495,6 @@ class CallICNexus final : public FeedbackNexus {
DCHECK(vector->IsCallIC(slot));
}
void Clear(Code* host);
void ConfigureUninitialized() override;
void ConfigureMonomorphicArray();
void ConfigureMonomorphic(Handle<JSFunction> function);
......@@ -534,7 +533,7 @@ class LoadICNexus : public FeedbackNexus {
DCHECK(vector->IsLoadIC(slot));
}
void Clear(Code* host);
void Clear() override { ConfigurePremonomorphic(); }
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
......@@ -568,7 +567,6 @@ class LoadGlobalICNexus : public FeedbackNexus {
}
void ConfigureMegamorphic() override { UNREACHABLE(); }
void Clear(Code* host);
void ConfigureUninitialized() override;
void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
......@@ -588,7 +586,7 @@ class KeyedLoadICNexus : public FeedbackNexus {
DCHECK(vector->IsKeyedLoadIC(slot));
}
void Clear(Code* host);
void Clear() override { ConfigurePremonomorphic(); }
// name can be a null handle for element loads.
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
......@@ -615,7 +613,7 @@ class StoreICNexus : public FeedbackNexus {
DCHECK(vector->IsStoreIC(slot));
}
void Clear(Code* host);
void Clear() override { ConfigurePremonomorphic(); }
void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
......@@ -636,7 +634,7 @@ class KeyedStoreICNexus : public FeedbackNexus {
DCHECK(vector->IsKeyedStoreIC(slot));
}
void Clear(Code* host);
void Clear() override { ConfigurePremonomorphic(); }
// name can be a null handle for element loads.
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
......@@ -667,8 +665,6 @@ class BinaryOpICNexus final : public FeedbackNexus {
DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot));
}
void Clear(Code* host);
InlineCacheState StateFromFeedback() const final;
BinaryOperationHint GetBinaryOperationFeedback() const;
......@@ -696,8 +692,6 @@ class CompareICNexus final : public FeedbackNexus {
DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot));
}
void Clear(Code* host);
InlineCacheState StateFromFeedback() const final;
CompareOperationHint GetCompareOperationFeedback() const;
......@@ -728,8 +722,6 @@ class StoreDataPropertyInLiteralICNexus : public FeedbackNexus {
vector->GetKind(slot));
}
void Clear(Code* host) { ConfigureUninitialized(); }
void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map);
InlineCacheState StateFromFeedback() const override;
......
......@@ -875,8 +875,7 @@ DEFINE_BOOL(never_compact, false,
"Never perform compaction on full GC - testing only")
DEFINE_BOOL(compact_code_space, true, "Compact code space on full collections")
DEFINE_BOOL(cleanup_code_caches_at_gc, true,
"Flush inline caches prior to mark compact collection and "
"flush code caches in maps during mark compact cycle.")
"Flush code caches in maps during mark compact cycle.")
DEFINE_BOOL(use_marking_progress_bar, true,
"Use a progress bar to scan large objects in increments when "
"incremental marking is active.")
......
......@@ -267,16 +267,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitCodeTarget(Heap* heap,
RelocInfo* rinfo) {
DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
// Monomorphic ICs are preserved when possible, but need to be flushed
// when they might be keeping a Context alive, or when the heap is about
// to be serialized.
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub() &&
(heap->isolate()->serializer_enabled() ||
target->ic_age() != heap->global_ic_age())) {
ICUtility::Clear(heap->isolate(), rinfo->pc(),
rinfo->host()->constant_pool());
target = Code::GetCodeFromTargetAddress(rinfo->target_address());
}
Code* host = rinfo->host();
heap->mark_compact_collector()->RecordRelocSlot(host, rinfo, target);
StaticVisitor::MarkObject(heap, target);
......@@ -461,9 +451,6 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSFunction(Map* map,
HeapObject* object) {
Heap* heap = map->GetHeap();
JSFunction* function = JSFunction::cast(object);
if (FLAG_cleanup_code_caches_at_gc) {
function->ClearTypeFeedbackInfoAtGCTime();
}
MarkCompactCollector* collector = heap->mark_compact_collector();
if (collector->is_code_flushing_enabled()) {
if (IsFlushable(heap, function)) {
......
......@@ -123,14 +123,6 @@ Handle<Map> IC::GetICCacheHolder(Handle<Map> map, Isolate* isolate,
}
Code* IC::get_host() {
return isolate()
->inner_pointer_to_code_cache()
->GetCacheEntry(address())
->code;
}
bool IC::AddressIsDeoptimizedCode() const {
return AddressIsDeoptimizedCode(isolate(), address());
}
......
......@@ -307,7 +307,7 @@ InlineCacheState IC::StateFromCode(Code* code) {
}
}
SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
JSFunction* IC::GetHostFunction() const {
// Compute the JavaScript frame for the frame pointer of this IC
// structure. We need this to be able to find the function
// corresponding to the frame.
......@@ -316,16 +316,7 @@ SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
// Find the function on the stack and both the active code for the
// function and the original code.
JSFunction* function = frame->function();
return function->shared();
}
Code* IC::GetCode() const {
HandleScope scope(isolate());
Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
Code* code = shared->code();
return code;
return frame->function();
}
static void LookupForRead(LookupIterator* it) {
......@@ -465,12 +456,14 @@ static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
}
// static
void IC::OnTypeFeedbackChanged(Isolate* isolate, Code* host) {
if (host->kind() != Code::FUNCTION) return;
void IC::OnFeedbackChanged(Isolate* isolate, JSFunction* host_function) {
Code* host = host_function->shared()->code();
TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
info->change_own_type_change_checksum();
host->set_profiler_ticks(0);
if (host->kind() == Code::FUNCTION) {
TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
info->change_own_type_change_checksum();
host->set_profiler_ticks(0);
}
isolate->runtime_profiler()->NotifyICChanged();
// TODO(2029): When an optimized function is patched, it would
// be nice to propagate the corresponding type information to its
......@@ -526,58 +519,6 @@ void IC::Clear(Isolate* isolate, Address address, Address constant_pool) {
}
}
void KeyedLoadIC::Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus) {
if (IsCleared(nexus)) return;
// Make sure to also clear the map used in inline fast cases. If we
// do not clear these maps, cached code can keep objects alive
// through the embedded maps.
nexus->ConfigurePremonomorphic();
OnTypeFeedbackChanged(isolate, host);
}
void CallIC::Clear(Isolate* isolate, Code* host, CallICNexus* nexus) {
// Determine our state.
Object* feedback = nexus->vector()->Get(nexus->slot());
State state = nexus->StateFromFeedback();
if (state != UNINITIALIZED && !feedback->IsAllocationSite()) {
nexus->ConfigureUninitialized();
// The change in state must be processed.
OnTypeFeedbackChanged(isolate, host);
}
}
void LoadIC::Clear(Isolate* isolate, Code* host, LoadICNexus* nexus) {
if (IsCleared(nexus)) return;
nexus->ConfigurePremonomorphic();
OnTypeFeedbackChanged(isolate, host);
}
void LoadGlobalIC::Clear(Isolate* isolate, Code* host,
LoadGlobalICNexus* nexus) {
if (IsCleared(nexus)) return;
nexus->ConfigureUninitialized();
OnTypeFeedbackChanged(isolate, host);
}
void StoreIC::Clear(Isolate* isolate, Code* host, StoreICNexus* nexus) {
if (IsCleared(nexus)) return;
nexus->ConfigurePremonomorphic();
OnTypeFeedbackChanged(isolate, host);
}
void KeyedStoreIC::Clear(Isolate* isolate, Code* host,
KeyedStoreICNexus* nexus) {
if (IsCleared(nexus)) return;
nexus->ConfigurePremonomorphic();
OnTypeFeedbackChanged(isolate, host);
}
void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
Address constant_pool) {
DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
......@@ -617,7 +558,7 @@ void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) {
}
vector_set_ = true;
OnTypeFeedbackChanged(isolate(), get_host());
OnFeedbackChanged(isolate(), GetHostFunction());
}
void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
......@@ -642,7 +583,7 @@ void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map,
}
vector_set_ = true;
OnTypeFeedbackChanged(isolate(), get_host());
OnFeedbackChanged(isolate(), GetHostFunction());
}
void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
......@@ -664,7 +605,7 @@ void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps,
}
vector_set_ = true;
OnTypeFeedbackChanged(isolate(), get_host());
OnFeedbackChanged(isolate(), GetHostFunction());
}
void IC::ConfigureVectorState(MapHandleList* maps,
......@@ -676,7 +617,7 @@ void IC::ConfigureVectorState(MapHandleList* maps,
nexus->ConfigurePolymorphic(maps, transitioned_maps, handlers);
vector_set_ = true;
OnTypeFeedbackChanged(isolate(), get_host());
OnFeedbackChanged(isolate(), GetHostFunction());
}
......@@ -1358,7 +1299,7 @@ Handle<Object> LoadIC::GetMapIndependentHandler(LookupIterator* lookup) {
return slow_stub();
}
// When debugging we need to go the slow path to flood the accessor.
if (GetSharedFunctionInfo()->HasDebugInfo()) {
if (GetHostFunction()->shared()->HasDebugInfo()) {
TRACE_HANDLER_STATS(isolate(), LoadIC_SlowStub);
return slow_stub();
}
......@@ -1504,7 +1445,7 @@ Handle<Object> LoadIC::CompileHandler(LookupIterator* lookup,
return ComputeHandler(lookup);
}
DCHECK(holder->HasFastProperties());
DCHECK(!GetSharedFunctionInfo()->HasDebugInfo());
DCHECK(!GetHostFunction()->shared()->HasDebugInfo());
Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
isolate());
CallOptimization call_optimization(getter);
......
......@@ -58,11 +58,6 @@ class IC {
Isolate* isolate,
CacheHolderFlag* flag);
static bool IsCleared(FeedbackNexus* nexus) {
InlineCacheState state = nexus->StateFromFeedback();
return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC;
}
static bool ICUseVector(Code::Kind kind) {
return kind == Code::LOAD_IC || kind == Code::LOAD_GLOBAL_IC ||
kind == Code::KEYED_LOAD_IC || kind == Code::STORE_IC ||
......@@ -82,15 +77,16 @@ class IC {
static inline bool IsHandler(Object* object);
// Nofity the IC system that a feedback has changed.
static void OnFeedbackChanged(Isolate* isolate, JSFunction* host_function);
protected:
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; }
// Get the shared function info of the caller.
SharedFunctionInfo* GetSharedFunctionInfo() const;
// Get the code object of the caller.
Code* GetCode() const;
// Get the caller function object.
JSFunction* GetHostFunction() const;
inline bool AddressIsDeoptimizedCode() const;
inline static bool AddressIsDeoptimizedCode(Isolate* isolate,
......@@ -135,8 +131,6 @@ class IC {
Address constant_pool);
static inline void SetTargetAtAddress(Address address, Code* target,
Address constant_pool);
// As a vector-based IC, type feedback must be updated differently.
static void OnTypeFeedbackChanged(Isolate* isolate, Code* host);
static void PostPatching(Address address, Code* target, Code* old_target);
void TraceHandlerCacheHitStats(LookupIterator* lookup);
......@@ -213,7 +207,6 @@ class IC {
}
FeedbackNexus* nexus() const { return nexus_; }
inline Code* get_host();
inline Code* target() const;
private:
......@@ -265,8 +258,6 @@ class CallIC : public IC {
: IC(EXTRA_CALL_FRAME, isolate, nexus) {
DCHECK(nexus != NULL);
}
static void Clear(Isolate* isolate, Code* host, CallICNexus* nexus);
};
......@@ -289,8 +280,6 @@ class LoadIC : public IC {
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
Handle<Name> name);
static void Clear(Isolate* isolate, Code* host, LoadICNexus* nexus);
protected:
virtual Handle<Code> slow_stub() const {
return isolate()->builtins()->LoadIC_Slow();
......@@ -330,8 +319,6 @@ class LoadGlobalIC : public LoadIC {
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Name> name);
static void Clear(Isolate* isolate, Code* host, LoadGlobalICNexus* nexus);
protected:
Handle<Code> slow_stub() const override {
return isolate()->builtins()->LoadGlobalIC_Slow();
......@@ -348,8 +335,6 @@ class KeyedLoadIC : public LoadIC {
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
Handle<Object> key);
static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
protected:
// receiver is HeapObject because it could be a String or a JSObject
void UpdateLoadElement(Handle<HeapObject> receiver);
......@@ -378,8 +363,6 @@ class StoreIC : public IC {
bool LookupForWrite(LookupIterator* it, Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode);
static void Clear(Isolate* isolate, Code* host, StoreICNexus* nexus);
protected:
// Stub accessors.
Handle<Code> slow_stub() const {
......@@ -423,8 +406,6 @@ class KeyedStoreIC : public StoreIC {
Handle<Object> name,
Handle<Object> value);
static void Clear(Isolate* isolate, Code* host, KeyedStoreICNexus* nexus);
protected:
void UpdateStoreElement(Handle<Map> receiver_map,
KeyedAccessStoreMode store_mode);
......
......@@ -13833,7 +13833,8 @@ void Code::ClearInlineCaches() {
RelocInfo* info = it.rinfo();
Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
if (target->is_inline_cache_stub()) {
IC::Clear(this->GetIsolate(), info->pc(), info->host()->constant_pool());
ICUtility::Clear(this->GetIsolate(), info->pc(),
info->host()->constant_pool());
}
}
}
......@@ -13870,14 +13871,7 @@ int AbstractCode::SourceStatementPosition(int offset) {
void JSFunction::ClearTypeFeedbackInfo() {
if (feedback_vector_cell()->value()->IsFeedbackVector()) {
FeedbackVector* vector = feedback_vector();
vector->ClearSlots(shared());
}
}
void JSFunction::ClearTypeFeedbackInfoAtGCTime() {
if (feedback_vector_cell()->value()->IsFeedbackVector()) {
FeedbackVector* vector = feedback_vector();
vector->ClearSlotsAtGCTime(shared());
vector->ClearSlots(this);
}
}
......
......@@ -7998,12 +7998,9 @@ class JSFunction: public JSObject {
inline bool has_feedback_vector() const;
static void EnsureLiterals(Handle<JSFunction> function);
// Unconditionally clear the type feedback vector (including vector ICs).
// Unconditionally clear the type feedback vector.
void ClearTypeFeedbackInfo();
// Clear the type feedback vector with a more subtle policy at GC time.
void ClearTypeFeedbackInfoAtGCTime();
// The initial map for an object created by this constructor.
inline Map* initial_map();
static void SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
......
......@@ -166,9 +166,11 @@ TEST(VectorSlotClearing) {
Factory* factory = isolate->factory();
Zone zone(isolate->allocator(), ZONE_NAME);
// We only test clearing FeedbackSlots, not FeedbackSlots.
// The reason is that FeedbackSlots need a full code environment
// to fully test (See VectorICProfilerStatistics test below).
CompileRun("function f() {};");
Handle<JSFunction> f = GetFunction("f");
// We only test clearing of a FeedbackSlotKind::kGeneral slots because all
// the other slot kinds require a host function for clearing.
FeedbackVectorSpec spec(&zone);
for (int i = 0; i < 5; i++) {
spec.AddGeneralSlot();
......@@ -183,12 +185,7 @@ TEST(VectorSlotClearing) {
Handle<AllocationSite> site = factory->NewAllocationSite();
vector->Set(helper.slot(2), *site);
// GC time clearing leaves slots alone.
vector->ClearSlotsAtGCTime(NULL);
Object* obj = vector->Get(helper.slot(1));
CHECK(obj->IsWeakCell() && !WeakCell::cast(obj)->cleared());
vector->ClearSlots(NULL);
vector->ClearSlots(*f);
// The feedback vector slots are cleared. AllocationSites are still granted
// an exemption from clearing, as are smis.
......
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