| 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) { |
| 21471 i::FLAG_native_code_counters = true; | 21472 i::FLAG_native_code_counters = true; |
| 21472 if (primary) { | 21473 if (primary) { |
| 21473 i::FLAG_test_primary_stub_cache = true; | 21474 i::FLAG_test_primary_stub_cache = true; |
| 21474 } else { | 21475 } else { |
| 21475 i::FLAG_test_secondary_stub_cache = true; | 21476 i::FLAG_test_secondary_stub_cache = true; |
| 21476 } | 21477 } |
| 21477 i::FLAG_crankshaft = false; | 21478 i::FLAG_crankshaft = false; |
| 21478 i::FLAG_turbo = false; | 21479 i::FLAG_turbo = false; |
| 21479 v8::Isolate::CreateParams create_params; | 21480 v8::Isolate::CreateParams create_params; |
| 21480 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); | 21481 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); |
| 21481 create_params.counter_lookup_callback = LookupCounter; | 21482 create_params.counter_lookup_callback = LookupCounter; |
| 21482 v8::Isolate* isolate = v8::Isolate::New(create_params); | 21483 v8::Isolate* isolate = v8::Isolate::New(create_params); |
| 21483 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
| 21484 | 21484 |
| 21485 if (!i_isolate->snapshot_available()) { | 21485 { |
| 21486 // The test is valid only for no-snapshot mode. | |
| 21487 v8::Isolate::Scope isolate_scope(isolate); | 21486 v8::Isolate::Scope isolate_scope(isolate); |
| 21488 LocalContext env(isolate); | 21487 LocalContext env(isolate); |
| 21489 v8::HandleScope scope(isolate); | 21488 v8::HandleScope scope(isolate); |
| 21490 | 21489 |
| 21490 { |
| 21491 // Enforce recompilation of all code stubs that access megamorphic stub |
| 21492 // cache to respect enabled native code counters and stub cache test mode |
| 21493 // flags. |
| 21494 i::CodeStub::Major code_stub_keys[] = { |
| 21495 i::CodeStub::LoadIC, i::CodeStub::LoadICTrampoline, |
| 21496 i::CodeStub::LoadICTF, i::CodeStub::LoadICTrampolineTF, |
| 21497 i::CodeStub::KeyedLoadIC, i::CodeStub::KeyedLoadICTrampoline, |
| 21498 i::CodeStub::StoreIC, i::CodeStub::StoreICTrampoline, |
| 21499 i::CodeStub::KeyedStoreIC, i::CodeStub::KeyedStoreICTrampoline, |
| 21500 }; |
| 21501 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 21502 i::UnseededNumberDictionary* dict = i_isolate->heap()->code_stubs(); |
| 21503 for (size_t i = 0; i < arraysize(code_stub_keys); i++) { |
| 21504 dict->DeleteKey(code_stub_keys[i]); |
| 21505 } |
| 21506 } |
| 21507 |
| 21491 int initial_probes = probes_counter; | 21508 int initial_probes = probes_counter; |
| 21492 int initial_misses = misses_counter; | 21509 int initial_misses = misses_counter; |
| 21493 int initial_updates = updates_counter; | 21510 int initial_updates = updates_counter; |
| 21494 CompileRun(kMegamorphicTestProgram); | 21511 CompileRun(kMegamorphicTestProgram); |
| 21495 int probes = probes_counter - initial_probes; | 21512 int probes = probes_counter - initial_probes; |
| 21496 int misses = misses_counter - initial_misses; | 21513 int misses = misses_counter - initial_misses; |
| 21497 int updates = updates_counter - initial_updates; | 21514 int updates = updates_counter - initial_updates; |
| 21498 const int kClassesCount = 6; | 21515 const int kClassesCount = 50; |
| 21516 const int kIterationsCount = 1000; |
| 21517 CHECK_LE(kClassesCount, updates); |
| 21499 // Check that updates and misses counts are bounded. | 21518 // Check that updates and misses counts are bounded. |
| 21500 CHECK_LE(kClassesCount, updates); | 21519 // If there are too many updates then most likely the stub cache does not |
| 21501 CHECK_LT(updates, kClassesCount * 3); | 21520 // work properly. |
| 21521 CHECK_LE(updates, kClassesCount * 2); |
| 21502 CHECK_LE(1, misses); | 21522 CHECK_LE(1, misses); |
| 21503 CHECK_LT(misses, kClassesCount * 2); | 21523 CHECK_LE(misses, kClassesCount * 2); |
| 21504 // 2 is for PREMONOMORPHIC and MONOMORPHIC states, | 21524 // 2 is for PREMONOMORPHIC and MONOMORPHIC states, |
| 21505 // 4 is for POLYMORPHIC states, | 21525 // 4 is for POLYMORPHIC states, |
| 21506 // and all the others probes are for MEGAMORPHIC state. | 21526 // and all the others probes are for MEGAMORPHIC state. |
| 21507 CHECK_EQ(10000 * kClassesCount - 2 - 4, probes); | 21527 CHECK_EQ(kIterationsCount * kClassesCount - 2 - 4, probes); |
| 21508 } | 21528 } |
| 21509 isolate->Dispose(); | 21529 isolate->Dispose(); |
| 21510 } | 21530 } |
| 21511 | 21531 |
| 21512 } // namespace | 21532 } // namespace |
| 21513 | 21533 |
| 21514 UNINITIALIZED_TEST(PrimaryStubCache) { StubCacheHelper(true); } | 21534 UNINITIALIZED_TEST(PrimaryStubCache) { |
| 21535 i::FLAG_tf_load_ic_stub = false; |
| 21536 TestStubCache(true); |
| 21537 } |
| 21515 | 21538 |
| 21516 UNINITIALIZED_TEST(SecondaryStubCache) { StubCacheHelper(false); } | 21539 UNINITIALIZED_TEST(SecondaryStubCache) { |
| 21540 i::FLAG_tf_load_ic_stub = false; |
| 21541 TestStubCache(false); |
| 21542 } |
| 21543 |
| 21544 UNINITIALIZED_TEST(PrimaryStubCacheTF) { |
| 21545 i::FLAG_tf_load_ic_stub = true; |
| 21546 TestStubCache(true); |
| 21547 } |
| 21548 |
| 21549 UNINITIALIZED_TEST(SecondaryStubCacheTF) { |
| 21550 i::FLAG_tf_load_ic_stub = true; |
| 21551 TestStubCache(false); |
| 21552 } |
| 21517 | 21553 |
| 21518 #endif // ENABLE_DISASSEMBLER | 21554 #endif // ENABLE_DISASSEMBLER |
| 21519 | 21555 |
| 21520 #ifdef DEBUG | 21556 #ifdef DEBUG |
| 21521 static int cow_arrays_created_runtime = 0; | 21557 static int cow_arrays_created_runtime = 0; |
| 21522 | 21558 |
| 21523 | 21559 |
| 21524 static int* LookupCounterCOWArrays(const char* name) { | 21560 static int* LookupCounterCOWArrays(const char* name) { |
| 21525 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) { | 21561 if (strcmp(name, "c:V8.COWArraysCreatedRuntime") == 0) { |
| 21526 return &cow_arrays_created_runtime; | 21562 return &cow_arrays_created_runtime; |
| (...skipping 3885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 25412 | 25448 |
| 25413 // Put the function into context1 and call it. Since the access check | 25449 // Put the function into context1 and call it. Since the access check |
| 25414 // callback always returns true, the call succeeds even though the tokens | 25450 // callback always returns true, the call succeeds even though the tokens |
| 25415 // are different. | 25451 // are different. |
| 25416 context1->Enter(); | 25452 context1->Enter(); |
| 25417 context1->Global()->Set(context1, v8_str("fun"), fun).FromJust(); | 25453 context1->Global()->Set(context1, v8_str("fun"), fun).FromJust(); |
| 25418 v8::Local<v8::Value> x_value = CompileRun("fun('x')"); | 25454 v8::Local<v8::Value> x_value = CompileRun("fun('x')"); |
| 25419 CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); | 25455 CHECK_EQ(42, x_value->Int32Value(context1).FromJust()); |
| 25420 context1->Exit(); | 25456 context1->Exit(); |
| 25421 } | 25457 } |
| OLD | NEW |