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, ...@@ -6006,23 +6006,6 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
// Load map of {object}. // Load map of {object}.
Node* object_map = LoadMap(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. // Goto runtime if {callable} is a Smi.
GotoIf(TaggedIsSmi(callable), &return_runtime); GotoIf(TaggedIsSmi(callable), &return_runtime);
...@@ -6069,11 +6052,6 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, ...@@ -6069,11 +6052,6 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
callable_prototype = var_callable_prototype.value(); 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. // Loop through the prototype chain looking for the {callable} prototype.
VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map); VARIABLE(var_object_map, MachineRepresentation::kTagged, object_map);
Label loop(this, &var_object_map); Label loop(this, &var_object_map);
...@@ -6106,19 +6084,15 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable, ...@@ -6106,19 +6084,15 @@ Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
} }
BIND(&return_true); BIND(&return_true);
StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true));
var_result.Bind(BooleanConstant(true)); var_result.Bind(BooleanConstant(true));
Goto(&return_result); Goto(&return_result);
BIND(&return_false); BIND(&return_false);
StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false));
var_result.Bind(BooleanConstant(false)); var_result.Bind(BooleanConstant(false));
Goto(&return_result); Goto(&return_result);
BIND(&return_runtime); BIND(&return_runtime);
{ {
// Invalidate the global instanceof cache.
StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0));
// Fallback to the runtime implementation. // Fallback to the runtime implementation.
var_result.Bind( var_result.Bind(
CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object)); CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
......
...@@ -753,19 +753,10 @@ void Heap::ExternalStringTable::ShrinkNewStrings(int position) { ...@@ -753,19 +753,10 @@ void Heap::ExternalStringTable::ShrinkNewStrings(int position) {
#endif #endif
} }
void Heap::ClearInstanceofCache() { set_instanceof_cache_function(Smi::kZero); }
Oddball* Heap::ToBoolean(bool condition) { Oddball* Heap::ToBoolean(bool condition) {
return condition ? true_value() : false_value(); 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 Heap::HashSeed() {
uint32_t seed = static_cast<uint32_t>(hash_seed()->value()); uint32_t seed = static_cast<uint32_t>(hash_seed()->value());
DCHECK(FLAG_randomize_hashes || seed == 0); DCHECK(FLAG_randomize_hashes || seed == 0);
......
...@@ -1542,8 +1542,6 @@ void Heap::MarkCompactPrologue() { ...@@ -1542,8 +1542,6 @@ void Heap::MarkCompactPrologue() {
isolate_->compilation_cache()->MarkCompactPrologue(); isolate_->compilation_cache()->MarkCompactPrologue();
CompletelyClearInstanceofCache();
FlushNumberStringCache(); FlushNumberStringCache();
ClearNormalizedMapCaches(); ClearNormalizedMapCaches();
} }
...@@ -2729,10 +2727,6 @@ void Heap::CreateInitialObjects() { ...@@ -2729,10 +2727,6 @@ void Heap::CreateInitialObjects() {
// expanding the dictionary during bootstrapping. // expanding the dictionary during bootstrapping.
set_code_stubs(*UnseededNumberDictionary::New(isolate(), 128)); 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()); HandleScope scope(isolate());
#define SYMBOL_INIT(name) \ #define SYMBOL_INIT(name) \
...@@ -2927,9 +2921,6 @@ void Heap::CreateInitialObjects() { ...@@ -2927,9 +2921,6 @@ void Heap::CreateInitialObjects() {
bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) {
switch (root_index) { switch (root_index) {
case kNumberStringCacheRootIndex: case kNumberStringCacheRootIndex:
case kInstanceofCacheFunctionRootIndex:
case kInstanceofCacheMapRootIndex:
case kInstanceofCacheAnswerRootIndex:
case kCodeStubsRootIndex: case kCodeStubsRootIndex:
case kScriptListRootIndex: case kScriptListRootIndex:
case kMaterializedObjectsRootIndex: case kMaterializedObjectsRootIndex:
......
...@@ -189,9 +189,6 @@ using v8::MemoryPressureLevel; ...@@ -189,9 +189,6 @@ using v8::MemoryPressureLevel;
V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \ V(FixedArray, single_character_string_cache, SingleCharacterStringCache) \
V(FixedArray, string_split_cache, StringSplitCache) \ V(FixedArray, string_split_cache, StringSplitCache) \
V(FixedArray, regexp_multiple_cache, RegExpMultipleCache) \ 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 */ \ /* Lists and dictionaries */ \
V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary) \ V(NameDictionary, empty_properties_dictionary, EmptyPropertiesDictionary) \
V(NameDictionary, public_symbol_table, PublicSymbolTable) \ V(NameDictionary, public_symbol_table, PublicSymbolTable) \
...@@ -739,9 +736,6 @@ class Heap { ...@@ -739,9 +736,6 @@ class Heap {
inline Address* OldSpaceAllocationTopAddress(); inline Address* OldSpaceAllocationTopAddress();
inline Address* OldSpaceAllocationLimitAddress(); 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. // FreeSpace objects have a null map after deserialization. Update the map.
void RepairFreeListsAfterDeserialization(); void RepairFreeListsAfterDeserialization();
...@@ -871,10 +865,6 @@ class Heap { ...@@ -871,10 +865,6 @@ class Heap {
void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature); 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 uint32_t HashSeed();
inline int NextScriptId(); inline int NextScriptId();
......
...@@ -595,7 +595,6 @@ void IncrementalMarking::StartMarking() { ...@@ -595,7 +595,6 @@ void IncrementalMarking::StartMarking() {
} }
#endif #endif
heap_->CompletelyClearInstanceofCache();
heap_->isolate()->compilation_cache()->MarkCompactPrologue(); heap_->isolate()->compilation_cache()->MarkCompactPrologue();
if (FLAG_concurrent_marking && !black_allocation_) { if (FLAG_concurrent_marking && !black_allocation_) {
......
...@@ -12553,7 +12553,6 @@ void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function, ...@@ -12553,7 +12553,6 @@ void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
} }
} }
isolate->heap()->ClearInstanceofCache();
} }
} // anonymous namespace } // anonymous namespace
...@@ -15279,7 +15278,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, ...@@ -15279,7 +15278,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
DCHECK(!object->IsAccessCheckNeeded()); DCHECK(!object->IsAccessCheckNeeded());
} }
Heap* heap = isolate->heap();
// Silently ignore the change if value is not a JSObject or null. // Silently ignore the change if value is not a JSObject or null.
// SpiderMonkey behaves this way. // SpiderMonkey behaves this way.
if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true); if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
...@@ -15347,7 +15345,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, ...@@ -15347,7 +15345,6 @@ Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
DCHECK(new_map->prototype() == *value); DCHECK(new_map->prototype() == *value);
JSObject::MigrateToMap(real_receiver, new_map); JSObject::MigrateToMap(real_receiver, new_map);
heap->ClearInstanceofCache();
DCHECK(size == object->Size()); DCHECK(size == object->Size());
return Just(true); 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