Commit f850b32d authored by bmeurer's avatar bmeurer Committed by Commit Bot

[cleanup] Remove instanceof cache.

The instanceof cache was initially introduced to speed up

  x instanceof y

where y is always the same constructor and x is always an object with
the same map. With the introduction of ES2015's @@hasInstance and the
Function.prototype[Symbol.hasInstance] handler (which calls into
OrdinaryHasInstance), this already became quite useless. It doesn't seem
to provide any real value (not sure it ever did for real), but it's
getting in the way of some useful refactorings (i.e. sharing logic
between OrdinaryHasInstance and Object.prototype.isPrototypeOf for
example).

So this CL completely removes the leftover bits of the instanceof cache,
including the GC and SetPrototype logic.

BUG=v8:6479,v8:6474
R=jgruber@chromium.org
TBR=ulan@chromium.org

Review-Url: https://codereview.chromium.org/2932263002
Cr-Commit-Position: refs/heads/master@{#45835}
parent d258efb6
......@@ -6006,23 +6006,6 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
// Load map of {object}.
Node* object_map = LoadMap(object);
// Lookup the {callable} and {object} map in the global instanceof cache.
// Note: This is safe because we clear the global instanceof cache whenever
// we change the prototype of any object.
Node* instanceof_cache_function =
LoadRoot(Heap::kInstanceofCacheFunctionRootIndex);
Node* instanceof_cache_map = LoadRoot(Heap::kInstanceofCacheMapRootIndex);
{
Label instanceof_cache_miss(this);
GotoIfNot(WordEqual(instanceof_cache_function, callable),
&instanceof_cache_miss);
GotoIfNot(WordEqual(instanceof_cache_map, object_map),
&instanceof_cache_miss);
var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex));
Goto(&return_result);
BIND(&instanceof_cache_miss);
}
// Goto runtime if {callable} is a Smi.
GotoIf(TaggedIsSmi(callable), &return_runtime);
......@@ -6069,11 +6052,6 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
callable_prototype = var_callable_prototype.value();
}
// Update the global instanceof cache with the current {object} map and
// {callable}. The cached answer will be set when it is known below.
StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, callable);
StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map);
// Loop through the prototype chain looking for the {callable} prototype.
VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map);
Label loop(this, &var_object_map);
......@@ -6106,19 +6084,15 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
}
BIND(&return_true);
StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true));
var_result.Bind(BooleanConstant(true));
Goto(&return_result);
BIND(&return_false);
StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false));
var_result.Bind(BooleanConstant(false));
Goto(&return_result);
BIND(&return_runtime);
{
// Invalidate the global instanceof cache.
StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0));
// Fallback to the runtime implementation.
var_result.Bind(
CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
......
......@@ -753,19 +753,10 @@ void Heap::ExternalStringTable::ShrinkNewStrings(int position) {
#endif
}
void Heap::ClearInstanceofCache() { set_instanceof_cache_function(Smi::kZero); }
Oddball* Heap::ToBoolean(bool condition) {
return condition ? true_value() : false_value();
}
void Heap::CompletelyClearInstanceofCache() {
set_instanceof_cache_map(Smi::kZero);
set_instanceof_cache_function(Smi::kZero);
}
uint32_t Heap::HashSeed() {
uint32_t seed = static_cast<uint32_t>(hash_seed()->value());
DCHECK(FLAG_randomize_hashes || seed == 0);
......
......@@ -1542,8 +1542,6 @@ void Heap::MarkCompactPrologue() {
isolate_->compilation_cache()->MarkCompactPrologue();
CompletelyClearInstanceofCache();
FlushNumberStringCache();
ClearNormalizedMapCaches();
}
......@@ -2729,10 +2727,6 @@ void Heap::CreateInitialObjects() {
// expanding the dictionary during bootstrapping.
set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128));
set_instanceof_cache_function(Smi::kZero);
set_instanceof_cache_map(Smi::kZero);
set_instanceof_cache_answer(Smi::kZero);
{
HandleScope scope(isolate());
#define SYMBOL_INIT(name) \
......@@ -2927,9 +2921,6 @@ void Heap::CreateInitialObjects() {
bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
switch (root_index) {
case kNumberStringCacheRootIndex:
case kInstanceofCacheFunctionRootIndex:
case kInstanceofCacheMapRootIndex:
case kInstanceofCacheAnswerRootIndex:
case kCodeStubsRootIndex:
case kScriptListRootIndex:
case kMaterializedObjectsRootIndex:
......
......@@ -189,9 +189,6 @@ using v8::MemoryPressureLevel;
V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \
V(FixedArray, string_split_cache, StringSplitCache) \
V(FixedArray, regexp_multiple_cache, RegExpMultipleCache) \
V(Object, instanceof_cache_function, InstanceofCacheFunction) \
V(Object, instanceof_cache_map, InstanceofCacheMap) \
V(Object, instanceof_cache_answer, InstanceofCacheAnswer) \
/* Lists and dictionaries */ \
V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary) \
V(NameDictionary, public_symbol_table, PublicSymbolTable) \
......@@ -739,9 +736,6 @@ class Heap {
inline Address* OldSpaceAllocationTopAddress();
inline Address* OldSpaceAllocationLimitAddress();
// Clear the Instanceof cache (used when a prototype changes).
inline void ClearInstanceofCache();
// FreeSpace objects have a null map after deserialization. Update the map.
void RepairFreeListsAfterDeserialization();
......@@ -871,10 +865,6 @@ class Heap {
void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature);
// Completely clear the Instanceof cache (to stop it keeping objects alive
// around a GC).
inline void CompletelyClearInstanceofCache();
inline uint32_t HashSeed();
inline int NextScriptId();
......
......@@ -595,7 +595,6 @@ void IncrementalMarking::StartMarking() {
}
#endif
heap_->CompletelyClearInstanceofCache();
heap_->isolate()->compilation_cache()->MarkCompactPrologue();
if (FLAG_concurrent_marking && !black_allocation_) {
......
......@@ -12553,7 +12553,6 @@ void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
}
}
isolate->heap()->ClearInstanceofCache();
}
} // anonymous namespace
......@@ -15279,7 +15278,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
DCHECK(!object->IsAccessCheckNeeded());
}
Heap* heap = isolate->heap();
// Silently ignore the change if value is not a JSObject or null.
// SpiderMonkey behaves this way.
if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
......@@ -15347,7 +15345,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
DCHECK(new_map->prototype() == *value);
JSObject::MigrateToMap(real_receiver, new_map);
heap->ClearInstanceofCache();
DCHECK(size == object->Size());
return Just(true);
}
......
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