OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 23 matching lines...) Expand all Loading... |
34 | 34 |
35 #if V8_OS_POSIX | 35 #if V8_OS_POSIX |
36 #include <unistd.h> // NOLINT | 36 #include <unistd.h> // NOLINT |
37 #endif | 37 #endif |
38 | 38 |
39 #include "include/v8-util.h" | 39 #include "include/v8-util.h" |
40 #include "src/api.h" | 40 #include "src/api.h" |
41 #include "src/arguments.h" | 41 #include "src/arguments.h" |
42 #include "src/base/platform/platform.h" | 42 #include "src/base/platform/platform.h" |
43 #include "src/base/smart-pointers.h" | 43 #include "src/base/smart-pointers.h" |
| 44 #include "src/code-stubs.h" |
44 #include "src/compilation-cache.h" | 45 #include "src/compilation-cache.h" |
45 #include "src/debug/debug.h" | 46 #include "src/debug/debug.h" |
46 #include "src/execution.h" | 47 #include "src/execution.h" |
47 #include "src/futex-emulation.h" | 48 #include "src/futex-emulation.h" |
48 #include "src/objects.h" | 49 #include "src/objects.h" |
49 #include "src/parsing/parser.h" | 50 #include "src/parsing/parser.h" |
50 #include "src/profiler/cpu-profiler.h" | 51 #include "src/profiler/cpu-profiler.h" |
51 #include "src/unicode-inl.h" | 52 #include "src/unicode-inl.h" |
52 #include "src/utils.h" | 53 #include "src/utils.h" |
53 #include "src/vm-state.h" | 54 #include "src/vm-state.h" |
(...skipping 21395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
21449 const char* kMegamorphicTestProgram = | 21450 const char* kMegamorphicTestProgram = |
21450 "function CreateClass(name) {\n" | 21451 "function CreateClass(name) {\n" |
21451 " var src = \n" | 21452 " var src = \n" |
21452 " ` function ${name}() {};` +\n" | 21453 " ` function ${name}() {};` +\n" |
21453 " ` ${name}.prototype.foo = function() {};` +\n" | 21454 " ` ${name}.prototype.foo = function() {};` +\n" |
21454 " ` ${name};\\n`;\n" | 21455 " ` ${name};\\n`;\n" |
21455 " return (0, eval)(src);\n" | 21456 " return (0, eval)(src);\n" |
21456 "}\n" | 21457 "}\n" |
21457 "function fooify(obj) { obj.foo(); };\n" | 21458 "function fooify(obj) { obj.foo(); };\n" |
21458 "var objs = [];\n" | 21459 "var objs = [];\n" |
21459 "for (var i = 0; i < 6; i++) {\n" | 21460 "for (var i = 0; i < 50; i++) {\n" |
21460 " var Class = CreateClass('Class' + i);\n" | 21461 " var Class = CreateClass('Class' + i);\n" |
21461 " var obj = new Class();\n" | 21462 " var obj = new Class();\n" |
21462 " objs.push(obj);\n" | 21463 " objs.push(obj);\n" |
21463 "}\n" | 21464 "}\n" |
21464 "for (var i = 0; i < 10000; i++) {\n" | 21465 "for (var i = 0; i < 1000; i++) {\n" |
21465 " for (var obj of objs) {\n" | 21466 " for (var obj of objs) {\n" |
21466 " fooify(obj);\n" | 21467 " fooify(obj);\n" |
21467 " }\n" | 21468 " }\n" |
21468 "}\n"; | 21469 "}\n"; |
21469 | 21470 |
21470 void StubCacheHelper(bool primary) { | 21471 void TestStubCache(bool primary) { |
| 21472 // The test does not work with interpreter because bytecode handlers taken |
| 21473 // from the snapshot already refer to ICs with disabled counters and there |
| 21474 // is no way to trigger bytecode handlers recompilation. |
| 21475 if (i::FLAG_ignition) return; |
| 21476 |
21471 i::FLAG_native_code_counters = true; | 21477 i::FLAG_native_code_counters = true; |
21472 if (primary) { | 21478 if (primary) { |
21473 i::FLAG_test_primary_stub_cache = true; | 21479 i::FLAG_test_primary_stub_cache = true; |
21474 } else { | 21480 } else { |
21475 i::FLAG_test_secondary_stub_cache = true; | 21481 i::FLAG_test_secondary_stub_cache = true; |
21476 } | 21482 } |
21477 i::FLAG_crankshaft = false; | 21483 i::FLAG_crankshaft = false; |
21478 i::FLAG_turbo = false; | 21484 i::FLAG_turbo = false; |
21479 v8::Isolate::CreateParams create_params; | 21485 v8::Isolate::CreateParams create_params; |
21480 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); | 21486 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); |
21481 create_params.counter_lookup_callback = LookupCounter; | 21487 create_params.counter_lookup_callback = LookupCounter; |
21482 v8::Isolate* isolate = v8::Isolate::New(create_params); | 21488 v8::Isolate* isolate = v8::Isolate::New(create_params); |
21483 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
21484 | 21489 |
21485 if (!i_isolate->snapshot_available()) { | 21490 { |
21486 // The test is valid only for no-snapshot mode. | |
21487 v8::Isolate::Scope isolate_scope(isolate); | 21491 v8::Isolate::Scope isolate_scope(isolate); |
21488 LocalContext env(isolate); | 21492 LocalContext env(isolate); |
21489 v8::HandleScope scope(isolate); | 21493 v8::HandleScope scope(isolate); |
21490 | 21494 |
| 21495 { |
| 21496 // Enforce recompilation of IC stubs that access megamorphic stub cache |
| 21497 // to respect enabled native code counters and stub cache test flags. |
| 21498 i::CodeStub::Major code_stub_keys[] = { |
| 21499 i::CodeStub::LoadIC, i::CodeStub::LoadICTrampoline, |
| 21500 i::CodeStub::LoadICTF, i::CodeStub::LoadICTrampolineTF, |
| 21501 i::CodeStub::KeyedLoadIC, i::CodeStub::KeyedLoadICTrampoline, |
| 21502 i::CodeStub::StoreIC, i::CodeStub::StoreICTrampoline, |
| 21503 i::CodeStub::KeyedStoreIC, i::CodeStub::KeyedStoreICTrampoline, |
| 21504 }; |
| 21505 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 21506 i::Heap* heap = i_isolate->heap(); |
| 21507 i::Handle<i::UnseededNumberDictionary> dict(heap->code_stubs()); |
| 21508 for (size_t i = 0; i < arraysize(code_stub_keys); i++) { |
| 21509 dict = i::UnseededNumberDictionary::DeleteKey(dict, code_stub_keys[i]); |
| 21510 } |
| 21511 heap->SetRootCodeStubs(*dict); |
| 21512 } |
| 21513 |
21491 int initial_probes = probes_counter; | 21514 int initial_probes = probes_counter; |
21492 int initial_misses = misses_counter; | 21515 int initial_misses = misses_counter; |
21493 int initial_updates = updates_counter; | 21516 int initial_updates = updates_counter; |
21494 CompileRun(kMegamorphicTestProgram); | 21517 CompileRun(kMegamorphicTestProgram); |
21495 int probes = probes_counter - initial_probes; | 21518 int probes = probes_counter - initial_probes; |
21496 int misses = misses_counter - initial_misses; | 21519 int misses = misses_counter - initial_misses; |
21497 int updates = updates_counter - initial_updates; | 21520 int updates = updates_counter - initial_updates; |
21498 const int kClassesCount = 6; | 21521 const int kClassesCount = 50; |
| 21522 const int kIterationsCount = 1000; |
| 21523 CHECK_LE(kClassesCount, updates); |
21499 // Check that updates and misses counts are bounded. | 21524 // Check that updates and misses counts are bounded. |
21500 CHECK_LE(kClassesCount, updates); | 21525 // If there are too many updates then most likely the stub cache does not |
21501 CHECK_LT(updates, kClassesCount * 3); | 21526 // work properly. |
| 21527 CHECK_LE(updates, kClassesCount * 2); |
21502 CHECK_LE(1, misses); | 21528 CHECK_LE(1, misses); |
21503 CHECK_LT(misses, kClassesCount * 2); | 21529 CHECK_LE(misses, kClassesCount * 2); |
21504 // 2 is for PREMONOMORPHIC and MONOMORPHIC states, | 21530 // 2 is for PREMONOMORPHIC and MONOMORPHIC states, |
21505 // 4 is for POLYMORPHIC states, | 21531 // 4 is for POLYMORPHIC states, |
21506 // and all the others probes are for MEGAMORPHIC state. | 21532 // and all the others probes are for MEGAMORPHIC state. |
21507 CHECK_EQ(10000 * kClassesCount - 2 - 4, probes); | 21533 CHECK_EQ(kIterationsCount * kClassesCount - 2 - 4, probes); |
21508 } | 21534 } |
21509 isolate->Dispose(); | 21535 isolate->Dispose(); |
21510 } | 21536 } |
21511 | 21537 |
21512 } // namespace | 21538 } // namespace |
21513 | 21539 |
21514 UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); } | 21540 UNINITIALIZED_TEST(PrimaryStubCache) { |
| 21541 i::FLAG_tf_load_ic_stub = false; |
| 21542 TestStubCache(true); |
| 21543 } |
21515 | 21544 |
21516 UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); } | 21545 UNINITIALIZED_TEST(SecondaryStubCache) { |
| 21546 i::FLAG_tf_load_ic_stub = false; |
| 21547 TestStubCache(false); |
| 21548 } |
| 21549 |
| 21550 UNINITIALIZED_TEST(PrimaryStubCacheTF) { |
| 21551 i::FLAG_tf_load_ic_stub = true; |
| 21552 TestStubCache(true); |
| 21553 } |
| 21554 |
| 21555 UNINITIALIZED_TEST(SecondaryStubCacheTF) { |
| 21556 i::FLAG_tf_load_ic_stub = true; |
| 21557 TestStubCache(false); |
| 21558 } |
21517 | 21559 |
21518 #endif // ENABLE_DISASSEMBLER | 21560 #endif // ENABLE_DISASSEMBLER |
21519 | 21561 |
21520 #ifdef DEBUG | 21562 #ifdef DEBUG |
21521 static int cow_arrays_created_runtime = 0; | 21563 static int cow_arrays_created_runtime = 0; |
21522 | 21564 |
21523 | 21565 |
21524 static int* LookupCounterCOWArrays(const char* name) { | 21566 static int* LookupCounterCOWArrays(const char* name) { |
21525 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) { | 21567 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) { |
21526 return &cow_arrays_created_runtime; | 21568 return &cow_arrays_created_runtime; |
(...skipping 3885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
25412 | 25454 |
25413 // Put the function into context1 and call it. Since the access check | 25455 // Put the function into context1 and call it. Since the access check |
25414 // callback always returns true, the call succeeds even though the tokens | 25456 // callback always returns true, the call succeeds even though the tokens |
25415 // are different. | 25457 // are different. |
25416 context1->Enter(); | 25458 context1->Enter(); |
25417 context1->Global()->Set(context1, v8_str("fun"), fun).FromJust(); | 25459 context1->Global()->Set(context1, v8_str("fun"), fun).FromJust(); |
25418 v8::Local<v8::Value> x_value = CompileRun("fun('x')"); | 25460 v8::Local<v8::Value> x_value = CompileRun("fun('x')"); |
25419 CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); | 25461 CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); |
25420 context1->Exit(); | 25462 context1->Exit(); |
25421 } | 25463 } |
OLD | NEW |