| 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 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 390 global_handles->Destroy(h4.location()); | 390 global_handles->Destroy(h4.location()); |
| 391 } | 391 } |
| 392 | 392 |
| 393 | 393 |
| 394 static bool WeakPointerCleared = false; | 394 static bool WeakPointerCleared = false; |
| 395 | 395 |
| 396 static void TestWeakGlobalHandleCallback(v8::Isolate* isolate, | 396 static void TestWeakGlobalHandleCallback(v8::Isolate* isolate, |
| 397 v8::Persistent<v8::Value>* handle, | 397 v8::Persistent<v8::Value>* handle, |
| 398 void* id) { | 398 void* id) { |
| 399 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true; | 399 if (1234 == reinterpret_cast<intptr_t>(id)) WeakPointerCleared = true; |
| 400 handle->Dispose(); | 400 handle->Reset(); |
| 401 } | 401 } |
| 402 | 402 |
| 403 | 403 |
| 404 TEST(WeakGlobalHandlesScavenge) { | 404 TEST(WeakGlobalHandlesScavenge) { |
| 405 i::FLAG_stress_compaction = false; | 405 i::FLAG_stress_compaction = false; |
| 406 CcTest::InitializeVM(); | 406 CcTest::InitializeVM(); |
| 407 Isolate* isolate = CcTest::i_isolate(); | 407 Isolate* isolate = CcTest::i_isolate(); |
| 408 Heap* heap = isolate->heap(); | 408 Heap* heap = isolate->heap(); |
| 409 Factory* factory = isolate->factory(); | 409 Factory* factory = isolate->factory(); |
| 410 GlobalHandles* global_handles = isolate->global_handles(); | 410 GlobalHandles* global_handles = isolate->global_handles(); |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 // We just initialized the VM, no heap allocation failure yet. | 753 // We just initialized the VM, no heap allocation failure yet. |
| 754 array->Initialize(0)->ToObjectChecked(); | 754 array->Initialize(0)->ToObjectChecked(); |
| 755 | 755 |
| 756 // Set array length to 0. | 756 // Set array length to 0. |
| 757 array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); | 757 array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); |
| 758 CHECK_EQ(Smi::FromInt(0), array->length()); | 758 CHECK_EQ(Smi::FromInt(0), array->length()); |
| 759 // Must be in fast mode. | 759 // Must be in fast mode. |
| 760 CHECK(array->HasFastSmiOrObjectElements()); | 760 CHECK(array->HasFastSmiOrObjectElements()); |
| 761 | 761 |
| 762 // array[length] = name. | 762 // array[length] = name. |
| 763 array->SetElement(0, *name, NONE, kNonStrictMode)->ToObjectChecked(); | 763 JSReceiver::SetElement(array, 0, name, NONE, kNonStrictMode); |
| 764 CHECK_EQ(Smi::FromInt(1), array->length()); | 764 CHECK_EQ(Smi::FromInt(1), array->length()); |
| 765 CHECK_EQ(array->GetElement(isolate, 0), *name); | 765 CHECK_EQ(array->GetElement(isolate, 0), *name); |
| 766 | 766 |
| 767 // Set array length with larger than smi value. | 767 // Set array length with larger than smi value. |
| 768 Handle<Object> length = | 768 Handle<Object> length = |
| 769 factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); | 769 factory->NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); |
| 770 array->SetElementsLength(*length)->ToObjectChecked(); | 770 array->SetElementsLength(*length)->ToObjectChecked(); |
| 771 | 771 |
| 772 uint32_t int_length = 0; | 772 uint32_t int_length = 0; |
| 773 CHECK(length->ToArrayIndex(&int_length)); | 773 CHECK(length->ToArrayIndex(&int_length)); |
| 774 CHECK_EQ(*length, array->length()); | 774 CHECK_EQ(*length, array->length()); |
| 775 CHECK(array->HasDictionaryElements()); // Must be in slow mode. | 775 CHECK(array->HasDictionaryElements()); // Must be in slow mode. |
| 776 | 776 |
| 777 // array[length] = name. | 777 // array[length] = name. |
| 778 array->SetElement(int_length, *name, NONE, kNonStrictMode)->ToObjectChecked(); | 778 JSReceiver::SetElement(array, int_length, name, NONE, kNonStrictMode); |
| 779 uint32_t new_int_length = 0; | 779 uint32_t new_int_length = 0; |
| 780 CHECK(array->length()->ToArrayIndex(&new_int_length)); | 780 CHECK(array->length()->ToArrayIndex(&new_int_length)); |
| 781 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); | 781 CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); |
| 782 CHECK_EQ(array->GetElement(isolate, int_length), *name); | 782 CHECK_EQ(array->GetElement(isolate, int_length), *name); |
| 783 CHECK_EQ(array->GetElement(isolate, 0), *name); | 783 CHECK_EQ(array->GetElement(isolate, 0), *name); |
| 784 } | 784 } |
| 785 | 785 |
| 786 | 786 |
| 787 TEST(JSObjectCopy) { | 787 TEST(JSObjectCopy) { |
| 788 CcTest::InitializeVM(); | 788 CcTest::InitializeVM(); |
| 789 Isolate* isolate = CcTest::i_isolate(); | 789 Isolate* isolate = CcTest::i_isolate(); |
| 790 Factory* factory = isolate->factory(); | 790 Factory* factory = isolate->factory(); |
| 791 | 791 |
| 792 v8::HandleScope sc(CcTest::isolate()); | 792 v8::HandleScope sc(CcTest::isolate()); |
| 793 String* object_string = String::cast(CcTest::heap()->Object_string()); | 793 String* object_string = String::cast(CcTest::heap()->Object_string()); |
| 794 Object* raw_object = CcTest::i_isolate()->context()->global_object()-> | 794 Object* raw_object = CcTest::i_isolate()->context()->global_object()-> |
| 795 GetProperty(object_string)->ToObjectChecked(); | 795 GetProperty(object_string)->ToObjectChecked(); |
| 796 JSFunction* object_function = JSFunction::cast(raw_object); | 796 JSFunction* object_function = JSFunction::cast(raw_object); |
| 797 Handle<JSFunction> constructor(object_function); | 797 Handle<JSFunction> constructor(object_function); |
| 798 Handle<JSObject> obj = factory->NewJSObject(constructor); | 798 Handle<JSObject> obj = factory->NewJSObject(constructor); |
| 799 Handle<String> first = factory->InternalizeUtf8String("first"); | 799 Handle<String> first = factory->InternalizeUtf8String("first"); |
| 800 Handle<String> second = factory->InternalizeUtf8String("second"); | 800 Handle<String> second = factory->InternalizeUtf8String("second"); |
| 801 | 801 |
| 802 Handle<Smi> one(Smi::FromInt(1), isolate); | 802 Handle<Smi> one(Smi::FromInt(1), isolate); |
| 803 Handle<Smi> two(Smi::FromInt(2), isolate); | 803 Handle<Smi> two(Smi::FromInt(2), isolate); |
| 804 | 804 |
| 805 JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); | 805 JSReceiver::SetProperty(obj, first, one, NONE, kNonStrictMode); |
| 806 JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); | 806 JSReceiver::SetProperty(obj, second, two, NONE, kNonStrictMode); |
| 807 | 807 |
| 808 obj->SetElement(0, *first, NONE, kNonStrictMode)->ToObjectChecked(); | 808 JSReceiver::SetElement(obj, 0, first, NONE, kNonStrictMode); |
| 809 obj->SetElement(1, *second, NONE, kNonStrictMode)->ToObjectChecked(); | 809 JSReceiver::SetElement(obj, 1, second, NONE, kNonStrictMode); |
| 810 | 810 |
| 811 // Make the clone. | 811 // Make the clone. |
| 812 Handle<JSObject> clone = JSObject::Copy(obj); | 812 Handle<JSObject> clone = JSObject::Copy(obj); |
| 813 CHECK(!clone.is_identical_to(obj)); | 813 CHECK(!clone.is_identical_to(obj)); |
| 814 | 814 |
| 815 CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 0)); | 815 CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 0)); |
| 816 CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 1)); | 816 CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 1)); |
| 817 | 817 |
| 818 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first)); | 818 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*first)); |
| 819 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); | 819 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); |
| 820 | 820 |
| 821 // Flip the values. | 821 // Flip the values. |
| 822 JSReceiver::SetProperty(clone, first, two, NONE, kNonStrictMode); | 822 JSReceiver::SetProperty(clone, first, two, NONE, kNonStrictMode); |
| 823 JSReceiver::SetProperty(clone, second, one, NONE, kNonStrictMode); | 823 JSReceiver::SetProperty(clone, second, one, NONE, kNonStrictMode); |
| 824 | 824 |
| 825 clone->SetElement(0, *second, NONE, kNonStrictMode)->ToObjectChecked(); | 825 JSReceiver::SetElement(clone, 0, second, NONE, kNonStrictMode); |
| 826 clone->SetElement(1, *first, NONE, kNonStrictMode)->ToObjectChecked(); | 826 JSReceiver::SetElement(clone, 1, first, NONE, kNonStrictMode); |
| 827 | 827 |
| 828 CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 0)); | 828 CHECK_EQ(obj->GetElement(isolate, 1), clone->GetElement(isolate, 0)); |
| 829 CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 1)); | 829 CHECK_EQ(obj->GetElement(isolate, 0), clone->GetElement(isolate, 1)); |
| 830 | 830 |
| 831 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first)); | 831 CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*first)); |
| 832 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second)); | 832 CHECK_EQ(obj->GetProperty(*first), clone->GetProperty(*second)); |
| 833 } | 833 } |
| 834 | 834 |
| 835 | 835 |
| 836 TEST(StringAllocation) { | 836 TEST(StringAllocation) { |
| (...skipping 943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 ctx2->Global()->Set(v8_str("o"), v); | 1780 ctx2->Global()->Set(v8_str("o"), v); |
| 1781 v8::Local<v8::Value> res = CompileRun( | 1781 v8::Local<v8::Value> res = CompileRun( |
| 1782 "function f() { return o.x; }" | 1782 "function f() { return o.x; }" |
| 1783 "for (var i = 0; i < 10; ++i) f();" | 1783 "for (var i = 0; i < 10; ++i) f();" |
| 1784 "%OptimizeFunctionOnNextCall(f);" | 1784 "%OptimizeFunctionOnNextCall(f);" |
| 1785 "f();"); | 1785 "f();"); |
| 1786 CHECK_EQ(42, res->Int32Value()); | 1786 CHECK_EQ(42, res->Int32Value()); |
| 1787 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1787 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1788 ctx2->Exit(); | 1788 ctx2->Exit(); |
| 1789 v8::Local<v8::Context>::New(isolate, ctx1)->Exit(); | 1789 v8::Local<v8::Context>::New(isolate, ctx1)->Exit(); |
| 1790 ctx1p.Dispose(); | 1790 ctx1p.Reset(); |
| 1791 v8::V8::ContextDisposedNotification(); | 1791 v8::V8::ContextDisposedNotification(); |
| 1792 } | 1792 } |
| 1793 CcTest::heap()->CollectAllAvailableGarbage(); | 1793 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1794 CHECK_EQ(2, NumberOfGlobalObjects()); | 1794 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1795 ctx2p.Dispose(); | 1795 ctx2p.Reset(); |
| 1796 CcTest::heap()->CollectAllAvailableGarbage(); | 1796 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1797 CHECK_EQ(0, NumberOfGlobalObjects()); | 1797 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1798 } | 1798 } |
| 1799 | 1799 |
| 1800 | 1800 |
| 1801 // Test that we don't embed functions from foreign contexts into | 1801 // Test that we don't embed functions from foreign contexts into |
| 1802 // optimized code. | 1802 // optimized code. |
| 1803 TEST(LeakNativeContextViaFunction) { | 1803 TEST(LeakNativeContextViaFunction) { |
| 1804 i::FLAG_allow_natives_syntax = true; | 1804 i::FLAG_allow_natives_syntax = true; |
| 1805 v8::Isolate* isolate = CcTest::isolate(); | 1805 v8::Isolate* isolate = CcTest::isolate(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1826 ctx2->Global()->Set(v8_str("o"), v); | 1826 ctx2->Global()->Set(v8_str("o"), v); |
| 1827 v8::Local<v8::Value> res = CompileRun( | 1827 v8::Local<v8::Value> res = CompileRun( |
| 1828 "function f(x) { return x(); }" | 1828 "function f(x) { return x(); }" |
| 1829 "for (var i = 0; i < 10; ++i) f(o);" | 1829 "for (var i = 0; i < 10; ++i) f(o);" |
| 1830 "%OptimizeFunctionOnNextCall(f);" | 1830 "%OptimizeFunctionOnNextCall(f);" |
| 1831 "f(o);"); | 1831 "f(o);"); |
| 1832 CHECK_EQ(42, res->Int32Value()); | 1832 CHECK_EQ(42, res->Int32Value()); |
| 1833 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1833 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1834 ctx2->Exit(); | 1834 ctx2->Exit(); |
| 1835 ctx1->Exit(); | 1835 ctx1->Exit(); |
| 1836 ctx1p.Dispose(); | 1836 ctx1p.Reset(); |
| 1837 v8::V8::ContextDisposedNotification(); | 1837 v8::V8::ContextDisposedNotification(); |
| 1838 } | 1838 } |
| 1839 CcTest::heap()->CollectAllAvailableGarbage(); | 1839 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1840 CHECK_EQ(2, NumberOfGlobalObjects()); | 1840 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1841 ctx2p.Dispose(); | 1841 ctx2p.Reset(); |
| 1842 CcTest::heap()->CollectAllAvailableGarbage(); | 1842 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1843 CHECK_EQ(0, NumberOfGlobalObjects()); | 1843 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1844 } | 1844 } |
| 1845 | 1845 |
| 1846 | 1846 |
| 1847 TEST(LeakNativeContextViaMapKeyed) { | 1847 TEST(LeakNativeContextViaMapKeyed) { |
| 1848 i::FLAG_allow_natives_syntax = true; | 1848 i::FLAG_allow_natives_syntax = true; |
| 1849 v8::Isolate* isolate = CcTest::isolate(); | 1849 v8::Isolate* isolate = CcTest::isolate(); |
| 1850 v8::HandleScope outer_scope(isolate); | 1850 v8::HandleScope outer_scope(isolate); |
| 1851 v8::Persistent<v8::Context> ctx1p; | 1851 v8::Persistent<v8::Context> ctx1p; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1870 ctx2->Global()->Set(v8_str("o"), v); | 1870 ctx2->Global()->Set(v8_str("o"), v); |
| 1871 v8::Local<v8::Value> res = CompileRun( | 1871 v8::Local<v8::Value> res = CompileRun( |
| 1872 "function f() { return o[0]; }" | 1872 "function f() { return o[0]; }" |
| 1873 "for (var i = 0; i < 10; ++i) f();" | 1873 "for (var i = 0; i < 10; ++i) f();" |
| 1874 "%OptimizeFunctionOnNextCall(f);" | 1874 "%OptimizeFunctionOnNextCall(f);" |
| 1875 "f();"); | 1875 "f();"); |
| 1876 CHECK_EQ(42, res->Int32Value()); | 1876 CHECK_EQ(42, res->Int32Value()); |
| 1877 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1877 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1878 ctx2->Exit(); | 1878 ctx2->Exit(); |
| 1879 ctx1->Exit(); | 1879 ctx1->Exit(); |
| 1880 ctx1p.Dispose(); | 1880 ctx1p.Reset(); |
| 1881 v8::V8::ContextDisposedNotification(); | 1881 v8::V8::ContextDisposedNotification(); |
| 1882 } | 1882 } |
| 1883 CcTest::heap()->CollectAllAvailableGarbage(); | 1883 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1884 CHECK_EQ(2, NumberOfGlobalObjects()); | 1884 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1885 ctx2p.Dispose(); | 1885 ctx2p.Reset(); |
| 1886 CcTest::heap()->CollectAllAvailableGarbage(); | 1886 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1887 CHECK_EQ(0, NumberOfGlobalObjects()); | 1887 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1888 } | 1888 } |
| 1889 | 1889 |
| 1890 | 1890 |
| 1891 TEST(LeakNativeContextViaMapProto) { | 1891 TEST(LeakNativeContextViaMapProto) { |
| 1892 i::FLAG_allow_natives_syntax = true; | 1892 i::FLAG_allow_natives_syntax = true; |
| 1893 v8::Isolate* isolate = CcTest::isolate(); | 1893 v8::Isolate* isolate = CcTest::isolate(); |
| 1894 v8::HandleScope outer_scope(isolate); | 1894 v8::HandleScope outer_scope(isolate); |
| 1895 v8::Persistent<v8::Context> ctx1p; | 1895 v8::Persistent<v8::Context> ctx1p; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1918 " p.__proto__ = o;" | 1918 " p.__proto__ = o;" |
| 1919 " return p.x;" | 1919 " return p.x;" |
| 1920 "}" | 1920 "}" |
| 1921 "for (var i = 0; i < 10; ++i) f();" | 1921 "for (var i = 0; i < 10; ++i) f();" |
| 1922 "%OptimizeFunctionOnNextCall(f);" | 1922 "%OptimizeFunctionOnNextCall(f);" |
| 1923 "f();"); | 1923 "f();"); |
| 1924 CHECK_EQ(42, res->Int32Value()); | 1924 CHECK_EQ(42, res->Int32Value()); |
| 1925 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1925 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
| 1926 ctx2->Exit(); | 1926 ctx2->Exit(); |
| 1927 ctx1->Exit(); | 1927 ctx1->Exit(); |
| 1928 ctx1p.Dispose(); | 1928 ctx1p.Reset(); |
| 1929 v8::V8::ContextDisposedNotification(); | 1929 v8::V8::ContextDisposedNotification(); |
| 1930 } | 1930 } |
| 1931 CcTest::heap()->CollectAllAvailableGarbage(); | 1931 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1932 CHECK_EQ(2, NumberOfGlobalObjects()); | 1932 CHECK_EQ(2, NumberOfGlobalObjects()); |
| 1933 ctx2p.Dispose(); | 1933 ctx2p.Reset(); |
| 1934 CcTest::heap()->CollectAllAvailableGarbage(); | 1934 CcTest::heap()->CollectAllAvailableGarbage(); |
| 1935 CHECK_EQ(0, NumberOfGlobalObjects()); | 1935 CHECK_EQ(0, NumberOfGlobalObjects()); |
| 1936 } | 1936 } |
| 1937 | 1937 |
| 1938 | 1938 |
| 1939 TEST(InstanceOfStubWriteBarrier) { | 1939 TEST(InstanceOfStubWriteBarrier) { |
| 1940 i::FLAG_allow_natives_syntax = true; | 1940 i::FLAG_allow_natives_syntax = true; |
| 1941 #ifdef VERIFY_HEAP | 1941 #ifdef VERIFY_HEAP |
| 1942 i::FLAG_verify_heap = true; | 1942 i::FLAG_verify_heap = true; |
| 1943 #endif | 1943 #endif |
| (...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2956 const char* data_; | 2956 const char* data_; |
| 2957 size_t length_; | 2957 size_t length_; |
| 2958 }; | 2958 }; |
| 2959 | 2959 |
| 2960 | 2960 |
| 2961 void ReleaseStackTraceDataTest(const char* source, const char* accessor) { | 2961 void ReleaseStackTraceDataTest(const char* source, const char* accessor) { |
| 2962 // Test that the data retained by the Error.stack accessor is released | 2962 // Test that the data retained by the Error.stack accessor is released |
| 2963 // after the first time the accessor is fired. We use external string | 2963 // after the first time the accessor is fired. We use external string |
| 2964 // to check whether the data is being released since the external string | 2964 // to check whether the data is being released since the external string |
| 2965 // resource's callback is fired when the external string is GC'ed. | 2965 // resource's callback is fired when the external string is GC'ed. |
| 2966 FLAG_use_ic = false; // ICs retain objects. | |
| 2967 FLAG_concurrent_recompilation = false; | |
| 2968 v8::HandleScope scope(CcTest::isolate()); | 2966 v8::HandleScope scope(CcTest::isolate()); |
| 2969 SourceResource* resource = new SourceResource(i::StrDup(source)); | 2967 SourceResource* resource = new SourceResource(i::StrDup(source)); |
| 2970 { | 2968 { |
| 2971 v8::HandleScope scope(CcTest::isolate()); | 2969 v8::HandleScope scope(CcTest::isolate()); |
| 2972 v8::Handle<v8::String> source_string = v8::String::NewExternal(resource); | 2970 v8::Handle<v8::String> source_string = v8::String::NewExternal(resource); |
| 2973 CcTest::heap()->CollectAllAvailableGarbage(); | 2971 CcTest::heap()->CollectAllAvailableGarbage(); |
| 2974 v8::Script::Compile(source_string)->Run(); | 2972 v8::Script::Compile(source_string)->Run(); |
| 2975 CHECK(!resource->IsDisposed()); | 2973 CHECK(!resource->IsDisposed()); |
| 2976 } | 2974 } |
| 2977 // CcTest::heap()->CollectAllAvailableGarbage(); | 2975 // CcTest::heap()->CollectAllAvailableGarbage(); |
| 2978 CHECK(!resource->IsDisposed()); | 2976 CHECK(!resource->IsDisposed()); |
| 2979 | 2977 |
| 2980 CompileRun(accessor); | 2978 CompileRun(accessor); |
| 2981 CcTest::heap()->CollectAllAvailableGarbage(); | 2979 CcTest::heap()->CollectAllAvailableGarbage(); |
| 2982 | 2980 |
| 2983 // External source has been released. | 2981 // External source has been released. |
| 2984 CHECK(resource->IsDisposed()); | 2982 CHECK(resource->IsDisposed()); |
| 2985 delete resource; | 2983 delete resource; |
| 2986 } | 2984 } |
| 2987 | 2985 |
| 2988 | 2986 |
| 2989 TEST(ReleaseStackTraceData) { | 2987 TEST(ReleaseStackTraceData) { |
| 2988 FLAG_use_ic = false; // ICs retain objects. |
| 2989 FLAG_concurrent_recompilation = false; |
| 2990 CcTest::InitializeVM(); | 2990 CcTest::InitializeVM(); |
| 2991 static const char* source1 = "var error = null; " | 2991 static const char* source1 = "var error = null; " |
| 2992 /* Normal Error */ "try { " | 2992 /* Normal Error */ "try { " |
| 2993 " throw new Error(); " | 2993 " throw new Error(); " |
| 2994 "} catch (e) { " | 2994 "} catch (e) { " |
| 2995 " error = e; " | 2995 " error = e; " |
| 2996 "} "; | 2996 "} "; |
| 2997 static const char* source2 = "var error = null; " | 2997 static const char* source2 = "var error = null; " |
| 2998 /* Stack overflow */ "try { " | 2998 /* Stack overflow */ "try { " |
| 2999 " (function f() { f(); })(); " | 2999 " (function f() { f(); })(); " |
| (...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3509 " var a = new Array(n);" | 3509 " var a = new Array(n);" |
| 3510 " for (var i = 0; i < n; i += 100) a[i] = i;" | 3510 " for (var i = 0; i < n; i += 100) a[i] = i;" |
| 3511 "};" | 3511 "};" |
| 3512 "f(10 * 1024 * 1024);"); | 3512 "f(10 * 1024 * 1024);"); |
| 3513 IncrementalMarking* marking = CcTest::heap()->incremental_marking(); | 3513 IncrementalMarking* marking = CcTest::heap()->incremental_marking(); |
| 3514 if (marking->IsStopped()) marking->Start(); | 3514 if (marking->IsStopped()) marking->Start(); |
| 3515 // This big step should be sufficient to mark the whole array. | 3515 // This big step should be sufficient to mark the whole array. |
| 3516 marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); | 3516 marking->Step(100 * MB, IncrementalMarking::NO_GC_VIA_STACK_GUARD); |
| 3517 ASSERT(marking->IsComplete()); | 3517 ASSERT(marking->IsComplete()); |
| 3518 } | 3518 } |
| 3519 |
| 3520 |
| 3521 TEST(DisableInlineAllocation) { |
| 3522 i::FLAG_allow_natives_syntax = true; |
| 3523 CcTest::InitializeVM(); |
| 3524 v8::HandleScope scope(CcTest::isolate()); |
| 3525 CompileRun("function test() {" |
| 3526 " var x = [];" |
| 3527 " for (var i = 0; i < 10; i++) {" |
| 3528 " x[i] = [ {}, [1,2,3], [1,x,3] ];" |
| 3529 " }" |
| 3530 "}" |
| 3531 "function run() {" |
| 3532 " %OptimizeFunctionOnNextCall(test);" |
| 3533 " test();" |
| 3534 " %DeoptimizeFunction(test);" |
| 3535 "}"); |
| 3536 |
| 3537 // Warm-up with inline allocation enabled. |
| 3538 CompileRun("test(); test(); run();"); |
| 3539 |
| 3540 // Run test with inline allocation disabled. |
| 3541 CcTest::heap()->DisableInlineAllocation(); |
| 3542 CompileRun("run()"); |
| 3543 |
| 3544 // Run test with inline allocation disabled and pretenuring. |
| 3545 CcTest::heap()->SetNewSpaceHighPromotionModeActive(true); |
| 3546 CompileRun("run()"); |
| 3547 |
| 3548 // Run test with inline allocation re-enabled. |
| 3549 CcTest::heap()->EnableInlineAllocation(); |
| 3550 CompileRun("run()"); |
| 3551 } |
| 3552 |
| 3553 |
| 3554 static int AllocationSitesCount(Heap* heap) { |
| 3555 int count = 0; |
| 3556 for (Object* site = heap->allocation_sites_list(); |
| 3557 !(site->IsUndefined()); |
| 3558 site = AllocationSite::cast(site)->weak_next()) { |
| 3559 count++; |
| 3560 } |
| 3561 return count; |
| 3562 } |
| 3563 |
| 3564 |
| 3565 TEST(EnsureAllocationSiteDependentCodesProcessed) { |
| 3566 if (i::FLAG_always_opt || !i::FLAG_crankshaft) return; |
| 3567 i::FLAG_allow_natives_syntax = true; |
| 3568 CcTest::InitializeVM(); |
| 3569 Isolate* isolate = CcTest::i_isolate(); |
| 3570 v8::internal::Heap* heap = CcTest::heap(); |
| 3571 GlobalHandles* global_handles = isolate->global_handles(); |
| 3572 |
| 3573 if (!isolate->use_crankshaft()) return; |
| 3574 |
| 3575 // The allocation site at the head of the list is ours. |
| 3576 Handle<AllocationSite> site; |
| 3577 { |
| 3578 LocalContext context; |
| 3579 v8::HandleScope scope(context->GetIsolate()); |
| 3580 |
| 3581 int count = AllocationSitesCount(heap); |
| 3582 CompileRun("var bar = function() { return (new Array()); };" |
| 3583 "var a = bar();" |
| 3584 "bar();" |
| 3585 "bar();"); |
| 3586 |
| 3587 // One allocation site should have been created. |
| 3588 int new_count = AllocationSitesCount(heap); |
| 3589 CHECK_EQ(new_count, (count + 1)); |
| 3590 site = Handle<AllocationSite>::cast( |
| 3591 global_handles->Create( |
| 3592 AllocationSite::cast(heap->allocation_sites_list()))); |
| 3593 |
| 3594 CompileRun("%OptimizeFunctionOnNextCall(bar); bar();"); |
| 3595 |
| 3596 DependentCode::GroupStartIndexes starts(site->dependent_code()); |
| 3597 CHECK_GE(starts.number_of_entries(), 1); |
| 3598 int index = starts.at(DependentCode::kAllocationSiteTransitionChangedGroup); |
| 3599 CHECK(site->dependent_code()->is_code_at(index)); |
| 3600 Code* function_bar = site->dependent_code()->code_at(index); |
| 3601 Handle<JSFunction> bar_handle = |
| 3602 v8::Utils::OpenHandle( |
| 3603 *v8::Handle<v8::Function>::Cast( |
| 3604 CcTest::global()->Get(v8_str("bar")))); |
| 3605 CHECK_EQ(bar_handle->code(), function_bar); |
| 3606 } |
| 3607 |
| 3608 // Now make sure that a gc should get rid of the function, even though we |
| 3609 // still have the allocation site alive. |
| 3610 for (int i = 0; i < 4; i++) { |
| 3611 heap->CollectAllGarbage(false); |
| 3612 } |
| 3613 |
| 3614 // The site still exists because of our global handle, but the code is no |
| 3615 // longer referred to by dependent_code(). |
| 3616 DependentCode::GroupStartIndexes starts(site->dependent_code()); |
| 3617 int index = starts.at(DependentCode::kAllocationSiteTransitionChangedGroup); |
| 3618 CHECK(!(site->dependent_code()->is_code_at(index))); |
| 3619 } |
| OLD | NEW |