[stubs] Fixed tests that prevented LoadICTF stubs from being enabled.
PrimaryStubCache and SecondaryStubCache: resurrected outdated tests (and enabled stub cache counters in the new LoadIC). TryProbeStubCache: decreased number of code objects created. Review-Url: https://codereview.chromium.org/2040193002 Cr-Commit-Position: refs/heads/master@{#36794}
This commit is contained in:
parent
2b38d3121b
commit
bcf3da279f
@ -1444,6 +1444,34 @@ Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
|
||||
Int32Constant(shift));
|
||||
}
|
||||
|
||||
void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) {
|
||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||
Node* counter_address = ExternalConstant(ExternalReference(counter));
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address,
|
||||
Int32Constant(value));
|
||||
}
|
||||
}
|
||||
|
||||
void CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) {
|
||||
DCHECK(delta > 0);
|
||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||
Node* counter_address = ExternalConstant(ExternalReference(counter));
|
||||
Node* value = Load(MachineType::Int32(), counter_address);
|
||||
value = Int32Add(value, Int32Constant(delta));
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeStubAssembler::DecrementCounter(StatsCounter* counter, int delta) {
|
||||
DCHECK(delta > 0);
|
||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||
Node* counter_address = ExternalConstant(ExternalReference(counter));
|
||||
Node* value = Load(MachineType::Int32(), counter_address);
|
||||
value = Int32Sub(value, Int32Constant(delta));
|
||||
StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
|
||||
Variable* var_index, Label* if_keyisunique,
|
||||
Label* if_bailout) {
|
||||
@ -2157,8 +2185,10 @@ void CodeStubAssembler::TryProbeStubCacheTable(
|
||||
#ifdef DEBUG
|
||||
if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
|
||||
Goto(if_miss);
|
||||
return;
|
||||
} else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
|
||||
Goto(if_miss);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// The {table_offset} holds the entry offset times four (due to masking
|
||||
@ -2202,10 +2232,13 @@ void CodeStubAssembler::TryProbeStubCache(
|
||||
StubCache* stub_cache, Code::Flags flags, compiler::Node* receiver,
|
||||
compiler::Node* name, Label* if_handler, Variable* var_handler,
|
||||
Label* if_miss) {
|
||||
Label try_secondary(this);
|
||||
Label try_secondary(this), miss(this);
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
IncrementCounter(counters->megamorphic_stub_cache_probes(), 1);
|
||||
|
||||
// Check that the {receiver} isn't a smi.
|
||||
GotoIf(WordIsSmi(receiver), if_miss);
|
||||
GotoIf(WordIsSmi(receiver), &miss);
|
||||
|
||||
Node* receiver_map = LoadMap(receiver);
|
||||
|
||||
@ -2220,8 +2253,13 @@ void CodeStubAssembler::TryProbeStubCache(
|
||||
Node* secondary_offset =
|
||||
StubCacheSecondaryOffset(name, flags, primary_offset);
|
||||
TryProbeStubCacheTable(stub_cache, kSecondary, secondary_offset, name,
|
||||
flags, receiver_map, if_handler, var_handler,
|
||||
if_miss);
|
||||
flags, receiver_map, if_handler, var_handler, &miss);
|
||||
}
|
||||
|
||||
Bind(&miss);
|
||||
{
|
||||
IncrementCounter(counters->megamorphic_stub_cache_misses(), 1);
|
||||
Goto(if_miss);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,6 +257,10 @@ class CodeStubAssembler : public compiler::CodeAssembler {
|
||||
compiler::Node* BitFieldDecode(compiler::Node* word32, uint32_t shift,
|
||||
uint32_t mask);
|
||||
|
||||
void SetCounter(StatsCounter* counter, int value);
|
||||
void IncrementCounter(StatsCounter* counter, int delta);
|
||||
void DecrementCounter(StatsCounter* counter, int delta);
|
||||
|
||||
// Various building blocks for stubs doing property lookups.
|
||||
void TryToName(compiler::Node* key, Label* if_keyisindex, Variable* var_index,
|
||||
Label* if_keyisunique, Label* if_bailout);
|
||||
|
@ -21481,14 +21481,18 @@ TEST(ScopedMicrotasks) {
|
||||
env->GetIsolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kAuto);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_DISASSEMBLER) && !defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
||||
// FLAG_test_primary_stub_cache and FLAG_test_secondary_stub_cache are read
|
||||
// only when ENABLE_DISASSEMBLER is not defined.
|
||||
// These tests are valid only for no-snapshot mode.
|
||||
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
static int probes_counter = 0;
|
||||
static int misses_counter = 0;
|
||||
static int updates_counter = 0;
|
||||
namespace {
|
||||
|
||||
int probes_counter = 0;
|
||||
int misses_counter = 0;
|
||||
int updates_counter = 0;
|
||||
|
||||
static int* LookupCounter(const char* name) {
|
||||
int* LookupCounter(const char* name) {
|
||||
if (strcmp(name, "c:V8.MegamorphicStubCacheProbes") == 0) {
|
||||
return &probes_counter;
|
||||
} else if (strcmp(name, "c:V8.MegamorphicStubCacheMisses") == 0) {
|
||||
@ -21499,24 +21503,28 @@ static int* LookupCounter(const char* name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* kMegamorphicTestProgram =
|
||||
"function CreateClass(name) {\n"
|
||||
" var src = \n"
|
||||
" ` function ${name}() {};` +\n"
|
||||
" ` ${name}.prototype.foo = function() {};` +\n"
|
||||
" ` ${name};\\n`;\n"
|
||||
" return (0, eval)(src);\n"
|
||||
"}\n"
|
||||
"function fooify(obj) { obj.foo(); };\n"
|
||||
"var objs = [];\n"
|
||||
"for (var i = 0; i < 6; i++) {\n"
|
||||
" var Class = CreateClass('Class' + i);\n"
|
||||
" var obj = new Class();\n"
|
||||
" objs.push(obj);\n"
|
||||
"}\n"
|
||||
"for (var i = 0; i < 10000; i++) {\n"
|
||||
" for (var obj of objs) {\n"
|
||||
" fooify(obj);\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
static const char* kMegamorphicTestProgram =
|
||||
"function ClassA() { };"
|
||||
"function ClassB() { };"
|
||||
"ClassA.prototype.foo = function() { };"
|
||||
"ClassB.prototype.foo = function() { };"
|
||||
"function fooify(obj) { obj.foo(); };"
|
||||
"var a = new ClassA();"
|
||||
"var b = new ClassB();"
|
||||
"for (var i = 0; i < 10000; i++) {"
|
||||
" fooify(a);"
|
||||
" fooify(b);"
|
||||
"}";
|
||||
#endif
|
||||
|
||||
|
||||
static void StubCacheHelper(bool primary) {
|
||||
#ifdef ENABLE_DISASSEMBLER
|
||||
void StubCacheHelper(bool primary) {
|
||||
i::FLAG_native_code_counters = true;
|
||||
if (primary) {
|
||||
i::FLAG_test_primary_stub_cache = true;
|
||||
@ -21524,36 +21532,46 @@ static void StubCacheHelper(bool primary) {
|
||||
i::FLAG_test_secondary_stub_cache = true;
|
||||
}
|
||||
i::FLAG_crankshaft = false;
|
||||
LocalContext env;
|
||||
env->GetIsolate()->SetCounterFunction(LookupCounter);
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
int initial_probes = probes_counter;
|
||||
int initial_misses = misses_counter;
|
||||
int initial_updates = updates_counter;
|
||||
CompileRun(kMegamorphicTestProgram);
|
||||
int probes = probes_counter - initial_probes;
|
||||
int misses = misses_counter - initial_misses;
|
||||
int updates = updates_counter - initial_updates;
|
||||
CHECK_LT(updates, 10);
|
||||
CHECK_LT(misses, 10);
|
||||
// TODO(verwaest): Update this test to overflow the degree of polymorphism
|
||||
// before megamorphism. The number of probes will only work once we teach the
|
||||
// serializer to embed references to counters in the stubs, given that the
|
||||
// megamorphic_stub_cache_probes is updated in a snapshot-generated stub.
|
||||
CHECK_GE(probes, 0);
|
||||
#endif
|
||||
i::FLAG_turbo = false;
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
|
||||
isolate->SetCounterFunction(LookupCounter);
|
||||
|
||||
{
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
LocalContext env(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
int initial_probes = probes_counter;
|
||||
int initial_misses = misses_counter;
|
||||
int initial_updates = updates_counter;
|
||||
CompileRun(kMegamorphicTestProgram);
|
||||
int probes = probes_counter - initial_probes;
|
||||
int misses = misses_counter - initial_misses;
|
||||
int updates = updates_counter - initial_updates;
|
||||
const int kClassesCount = 6;
|
||||
// Check that updates and misses counts are bounded.
|
||||
CHECK_LE(kClassesCount, updates);
|
||||
CHECK_LT(updates, kClassesCount * 3);
|
||||
CHECK_LE(1, misses);
|
||||
CHECK_LT(misses, kClassesCount * 2);
|
||||
// 2 is for PREMONOMORPHIC and MONOMORPHIC states,
|
||||
// 4 is for POLYMORPHIC states,
|
||||
// and all the others probes are for MEGAMORPHIC state.
|
||||
CHECK_EQ(10000 * kClassesCount - 2 - 4, probes);
|
||||
}
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(SecondaryStubCache) {
|
||||
StubCacheHelper(true);
|
||||
}
|
||||
UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); }
|
||||
|
||||
UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); }
|
||||
|
||||
TEST(PrimaryStubCache) {
|
||||
StubCacheHelper(false);
|
||||
}
|
||||
|
||||
#endif // ENABLE_DISASSEMBLER && !V8_USE_EXTERNAL_STARTUP_DATA
|
||||
|
||||
#ifdef DEBUG
|
||||
static int cow_arrays_created_runtime = 0;
|
||||
|
@ -1328,7 +1328,7 @@ TEST(TryProbeStubCache) {
|
||||
}
|
||||
|
||||
// Generate some number of handlers.
|
||||
for (int i = 0; i < StubCache::kSecondaryTableSize; i++) {
|
||||
for (int i = 0; i < 30; i++) {
|
||||
Code::Kind code_kind;
|
||||
switch (rand_gen.NextInt(4)) {
|
||||
case 0:
|
||||
|
Loading…
Reference in New Issue
Block a user