Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: test/cctest/test-heap.cc

Issue 15964004: remove most V8_ALLOW_ACCESS_TO_* defines from test classes (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: comment addressed Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « test/cctest/test-hashing.cc ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 // TODO(dcarney): remove
31 #define V8_ALLOW_ACCESS_TO_PERSISTENT_ARROW
32 #define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
33
34 #include "v8.h" 30 #include "v8.h"
35 31
36 #include "compilation-cache.h" 32 #include "compilation-cache.h"
37 #include "execution.h" 33 #include "execution.h"
38 #include "factory.h" 34 #include "factory.h"
39 #include "macro-assembler.h" 35 #include "macro-assembler.h"
40 #include "global-handles.h" 36 #include "global-handles.h"
41 #include "stub-cache.h" 37 #include "stub-cache.h"
42 #include "cctest.h" 38 #include "cctest.h"
43 39
(...skipping 1612 matching lines...) Expand 10 before | Expand all | Expand 10 after
1656 return count; 1652 return count;
1657 } 1653 }
1658 1654
1659 1655
1660 // Test that we don't embed maps from foreign contexts into 1656 // Test that we don't embed maps from foreign contexts into
1661 // optimized code. 1657 // optimized code.
1662 TEST(LeakNativeContextViaMap) { 1658 TEST(LeakNativeContextViaMap) {
1663 i::FLAG_allow_natives_syntax = true; 1659 i::FLAG_allow_natives_syntax = true;
1664 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 1660 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1665 v8::HandleScope outer_scope(isolate); 1661 v8::HandleScope outer_scope(isolate);
1666 v8::Persistent<v8::Context> ctx1; 1662 v8::Persistent<v8::Context> ctx1p;
1667 v8::Persistent<v8::Context> ctx2; 1663 v8::Persistent<v8::Context> ctx2p;
1668 { 1664 {
1669 v8::HandleScope scope(isolate); 1665 v8::HandleScope scope(isolate);
1670 ctx1.Reset(isolate, v8::Context::New(isolate)); 1666 ctx1p.Reset(isolate, v8::Context::New(isolate));
1671 ctx2.Reset(isolate, v8::Context::New(isolate)); 1667 ctx2p.Reset(isolate, v8::Context::New(isolate));
1668 v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1672 } 1669 }
1673 ctx1->Enter();
1674 1670
1675 HEAP->CollectAllAvailableGarbage(); 1671 HEAP->CollectAllAvailableGarbage();
1676 CHECK_EQ(4, NumberOfGlobalObjects()); 1672 CHECK_EQ(4, NumberOfGlobalObjects());
1677 1673
1678 { 1674 {
1679 v8::HandleScope inner_scope(v8::Isolate::GetCurrent()); 1675 v8::HandleScope inner_scope(isolate);
1680 CompileRun("var v = {x: 42}"); 1676 CompileRun("var v = {x: 42}");
1677 v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1678 v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1681 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); 1679 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1682 ctx2->Enter(); 1680 ctx2->Enter();
1683 ctx2->Global()->Set(v8_str("o"), v); 1681 ctx2->Global()->Set(v8_str("o"), v);
1684 v8::Local<v8::Value> res = CompileRun( 1682 v8::Local<v8::Value> res = CompileRun(
1685 "function f() { return o.x; }" 1683 "function f() { return o.x; }"
1686 "for (var i = 0; i < 10; ++i) f();" 1684 "for (var i = 0; i < 10; ++i) f();"
1687 "%OptimizeFunctionOnNextCall(f);" 1685 "%OptimizeFunctionOnNextCall(f);"
1688 "f();"); 1686 "f();");
1689 CHECK_EQ(42, res->Int32Value()); 1687 CHECK_EQ(42, res->Int32Value());
1690 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); 1688 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1691 ctx2->Exit(); 1689 ctx2->Exit();
1692 ctx1->Exit(); 1690 v8::Local<v8::Context>::New(isolate, ctx1)->Exit();
1693 ctx1.Dispose(ctx1->GetIsolate()); 1691 ctx1p.Dispose(isolate);
1694 v8::V8::ContextDisposedNotification(); 1692 v8::V8::ContextDisposedNotification();
1695 } 1693 }
1696 HEAP->CollectAllAvailableGarbage(); 1694 HEAP->CollectAllAvailableGarbage();
1697 CHECK_EQ(2, NumberOfGlobalObjects()); 1695 CHECK_EQ(2, NumberOfGlobalObjects());
1698 ctx2.Dispose(ctx2->GetIsolate()); 1696 ctx2p.Dispose(isolate);
1699 HEAP->CollectAllAvailableGarbage(); 1697 HEAP->CollectAllAvailableGarbage();
1700 CHECK_EQ(0, NumberOfGlobalObjects()); 1698 CHECK_EQ(0, NumberOfGlobalObjects());
1701 } 1699 }
1702 1700
1703 1701
1704 // Test that we don't embed functions from foreign contexts into 1702 // Test that we don't embed functions from foreign contexts into
1705 // optimized code. 1703 // optimized code.
1706 TEST(LeakNativeContextViaFunction) { 1704 TEST(LeakNativeContextViaFunction) {
1707 i::FLAG_allow_natives_syntax = true; 1705 i::FLAG_allow_natives_syntax = true;
1708 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 1706 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1709 v8::HandleScope outer_scope(isolate); 1707 v8::HandleScope outer_scope(isolate);
1710 v8::Persistent<v8::Context> ctx1; 1708 v8::Persistent<v8::Context> ctx1p;
1711 v8::Persistent<v8::Context> ctx2; 1709 v8::Persistent<v8::Context> ctx2p;
1712 { 1710 {
1713 v8::HandleScope scope(isolate); 1711 v8::HandleScope scope(isolate);
1714 ctx1.Reset(isolate, v8::Context::New(isolate)); 1712 ctx1p.Reset(isolate, v8::Context::New(isolate));
1715 ctx2.Reset(isolate, v8::Context::New(isolate)); 1713 ctx2p.Reset(isolate, v8::Context::New(isolate));
1714 v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1716 } 1715 }
1717 ctx1->Enter();
1718 1716
1719 HEAP->CollectAllAvailableGarbage(); 1717 HEAP->CollectAllAvailableGarbage();
1720 CHECK_EQ(4, NumberOfGlobalObjects()); 1718 CHECK_EQ(4, NumberOfGlobalObjects());
1721 1719
1722 { 1720 {
1723 v8::HandleScope inner_scope(v8::Isolate::GetCurrent()); 1721 v8::HandleScope inner_scope(isolate);
1724 CompileRun("var v = function() { return 42; }"); 1722 CompileRun("var v = function() { return 42; }");
1723 v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1724 v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1725 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); 1725 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1726 ctx2->Enter(); 1726 ctx2->Enter();
1727 ctx2->Global()->Set(v8_str("o"), v); 1727 ctx2->Global()->Set(v8_str("o"), v);
1728 v8::Local<v8::Value> res = CompileRun( 1728 v8::Local<v8::Value> res = CompileRun(
1729 "function f(x) { return x(); }" 1729 "function f(x) { return x(); }"
1730 "for (var i = 0; i < 10; ++i) f(o);" 1730 "for (var i = 0; i < 10; ++i) f(o);"
1731 "%OptimizeFunctionOnNextCall(f);" 1731 "%OptimizeFunctionOnNextCall(f);"
1732 "f(o);"); 1732 "f(o);");
1733 CHECK_EQ(42, res->Int32Value()); 1733 CHECK_EQ(42, res->Int32Value());
1734 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); 1734 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1735 ctx2->Exit(); 1735 ctx2->Exit();
1736 ctx1->Exit(); 1736 ctx1->Exit();
1737 ctx1.Dispose(ctx1->GetIsolate()); 1737 ctx1p.Dispose(ctx1->GetIsolate());
1738 v8::V8::ContextDisposedNotification(); 1738 v8::V8::ContextDisposedNotification();
1739 } 1739 }
1740 HEAP->CollectAllAvailableGarbage(); 1740 HEAP->CollectAllAvailableGarbage();
1741 CHECK_EQ(2, NumberOfGlobalObjects()); 1741 CHECK_EQ(2, NumberOfGlobalObjects());
1742 ctx2.Dispose(ctx2->GetIsolate()); 1742 ctx2p.Dispose(isolate);
1743 HEAP->CollectAllAvailableGarbage(); 1743 HEAP->CollectAllAvailableGarbage();
1744 CHECK_EQ(0, NumberOfGlobalObjects()); 1744 CHECK_EQ(0, NumberOfGlobalObjects());
1745 } 1745 }
1746 1746
1747 1747
1748 TEST(LeakNativeContextViaMapKeyed) { 1748 TEST(LeakNativeContextViaMapKeyed) {
1749 i::FLAG_allow_natives_syntax = true; 1749 i::FLAG_allow_natives_syntax = true;
1750 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 1750 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1751 v8::HandleScope outer_scope(isolate); 1751 v8::HandleScope outer_scope(isolate);
1752 v8::Persistent<v8::Context> ctx1; 1752 v8::Persistent<v8::Context> ctx1p;
1753 v8::Persistent<v8::Context> ctx2; 1753 v8::Persistent<v8::Context> ctx2p;
1754 { 1754 {
1755 v8::HandleScope scope(isolate); 1755 v8::HandleScope scope(isolate);
1756 ctx1.Reset(isolate, v8::Context::New(isolate)); 1756 ctx1p.Reset(isolate, v8::Context::New(isolate));
1757 ctx2.Reset(isolate, v8::Context::New(isolate)); 1757 ctx2p.Reset(isolate, v8::Context::New(isolate));
1758 v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1758 } 1759 }
1759 ctx1->Enter();
1760 1760
1761 HEAP->CollectAllAvailableGarbage(); 1761 HEAP->CollectAllAvailableGarbage();
1762 CHECK_EQ(4, NumberOfGlobalObjects()); 1762 CHECK_EQ(4, NumberOfGlobalObjects());
1763 1763
1764 { 1764 {
1765 v8::HandleScope inner_scope(v8::Isolate::GetCurrent()); 1765 v8::HandleScope inner_scope(isolate);
1766 CompileRun("var v = [42, 43]"); 1766 CompileRun("var v = [42, 43]");
1767 v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1768 v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1767 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); 1769 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1768 ctx2->Enter(); 1770 ctx2->Enter();
1769 ctx2->Global()->Set(v8_str("o"), v); 1771 ctx2->Global()->Set(v8_str("o"), v);
1770 v8::Local<v8::Value> res = CompileRun( 1772 v8::Local<v8::Value> res = CompileRun(
1771 "function f() { return o[0]; }" 1773 "function f() { return o[0]; }"
1772 "for (var i = 0; i < 10; ++i) f();" 1774 "for (var i = 0; i < 10; ++i) f();"
1773 "%OptimizeFunctionOnNextCall(f);" 1775 "%OptimizeFunctionOnNextCall(f);"
1774 "f();"); 1776 "f();");
1775 CHECK_EQ(42, res->Int32Value()); 1777 CHECK_EQ(42, res->Int32Value());
1776 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); 1778 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1777 ctx2->Exit(); 1779 ctx2->Exit();
1778 ctx1->Exit(); 1780 ctx1->Exit();
1779 ctx1.Dispose(ctx1->GetIsolate()); 1781 ctx1p.Dispose(ctx1->GetIsolate());
1780 v8::V8::ContextDisposedNotification(); 1782 v8::V8::ContextDisposedNotification();
1781 } 1783 }
1782 HEAP->CollectAllAvailableGarbage(); 1784 HEAP->CollectAllAvailableGarbage();
1783 CHECK_EQ(2, NumberOfGlobalObjects()); 1785 CHECK_EQ(2, NumberOfGlobalObjects());
1784 ctx2.Dispose(ctx2->GetIsolate()); 1786 ctx2p.Dispose(isolate);
1785 HEAP->CollectAllAvailableGarbage(); 1787 HEAP->CollectAllAvailableGarbage();
1786 CHECK_EQ(0, NumberOfGlobalObjects()); 1788 CHECK_EQ(0, NumberOfGlobalObjects());
1787 } 1789 }
1788 1790
1789 1791
1790 TEST(LeakNativeContextViaMapProto) { 1792 TEST(LeakNativeContextViaMapProto) {
1791 i::FLAG_allow_natives_syntax = true; 1793 i::FLAG_allow_natives_syntax = true;
1792 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 1794 v8::Isolate* isolate = v8::Isolate::GetCurrent();
1793 v8::HandleScope outer_scope(isolate); 1795 v8::HandleScope outer_scope(isolate);
1794 v8::Persistent<v8::Context> ctx1; 1796 v8::Persistent<v8::Context> ctx1p;
1795 v8::Persistent<v8::Context> ctx2; 1797 v8::Persistent<v8::Context> ctx2p;
1796 { 1798 {
1797 v8::HandleScope scope(isolate); 1799 v8::HandleScope scope(isolate);
1798 ctx1.Reset(isolate, v8::Context::New(isolate)); 1800 ctx1p.Reset(isolate, v8::Context::New(isolate));
1799 ctx2.Reset(isolate, v8::Context::New(isolate)); 1801 ctx2p.Reset(isolate, v8::Context::New(isolate));
1802 v8::Local<v8::Context>::New(isolate, ctx1p)->Enter();
1800 } 1803 }
1801 ctx1->Enter();
1802 1804
1803 HEAP->CollectAllAvailableGarbage(); 1805 HEAP->CollectAllAvailableGarbage();
1804 CHECK_EQ(4, NumberOfGlobalObjects()); 1806 CHECK_EQ(4, NumberOfGlobalObjects());
1805 1807
1806 { 1808 {
1807 v8::HandleScope inner_scope(v8::Isolate::GetCurrent()); 1809 v8::HandleScope inner_scope(isolate);
1808 CompileRun("var v = { y: 42}"); 1810 CompileRun("var v = { y: 42}");
1811 v8::Local<v8::Context> ctx1 = v8::Local<v8::Context>::New(isolate, ctx1p);
1812 v8::Local<v8::Context> ctx2 = v8::Local<v8::Context>::New(isolate, ctx2p);
1809 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); 1813 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v"));
1810 ctx2->Enter(); 1814 ctx2->Enter();
1811 ctx2->Global()->Set(v8_str("o"), v); 1815 ctx2->Global()->Set(v8_str("o"), v);
1812 v8::Local<v8::Value> res = CompileRun( 1816 v8::Local<v8::Value> res = CompileRun(
1813 "function f() {" 1817 "function f() {"
1814 " var p = {x: 42};" 1818 " var p = {x: 42};"
1815 " p.__proto__ = o;" 1819 " p.__proto__ = o;"
1816 " return p.x;" 1820 " return p.x;"
1817 "}" 1821 "}"
1818 "for (var i = 0; i < 10; ++i) f();" 1822 "for (var i = 0; i < 10; ++i) f();"
1819 "%OptimizeFunctionOnNextCall(f);" 1823 "%OptimizeFunctionOnNextCall(f);"
1820 "f();"); 1824 "f();");
1821 CHECK_EQ(42, res->Int32Value()); 1825 CHECK_EQ(42, res->Int32Value());
1822 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); 1826 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0));
1823 ctx2->Exit(); 1827 ctx2->Exit();
1824 ctx1->Exit(); 1828 ctx1->Exit();
1825 ctx1.Dispose(ctx1->GetIsolate()); 1829 ctx1p.Dispose(isolate);
1826 v8::V8::ContextDisposedNotification(); 1830 v8::V8::ContextDisposedNotification();
1827 } 1831 }
1828 HEAP->CollectAllAvailableGarbage(); 1832 HEAP->CollectAllAvailableGarbage();
1829 CHECK_EQ(2, NumberOfGlobalObjects()); 1833 CHECK_EQ(2, NumberOfGlobalObjects());
1830 ctx2.Dispose(ctx2->GetIsolate()); 1834 ctx2p.Dispose(isolate);
1831 HEAP->CollectAllAvailableGarbage(); 1835 HEAP->CollectAllAvailableGarbage();
1832 CHECK_EQ(0, NumberOfGlobalObjects()); 1836 CHECK_EQ(0, NumberOfGlobalObjects());
1833 } 1837 }
1834 1838
1835 1839
1836 TEST(InstanceOfStubWriteBarrier) { 1840 TEST(InstanceOfStubWriteBarrier) {
1837 i::FLAG_allow_natives_syntax = true; 1841 i::FLAG_allow_natives_syntax = true;
1838 #ifdef VERIFY_HEAP 1842 #ifdef VERIFY_HEAP
1839 i::FLAG_verify_heap = true; 1843 i::FLAG_verify_heap = true;
1840 #endif 1844 #endif
(...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after
3096 } 3100 }
3097 // An entire block of handles has been filled. 3101 // An entire block of handles has been filled.
3098 // Next handle would require a new block. 3102 // Next handle would require a new block.
3099 ASSERT(data->next == data->limit); 3103 ASSERT(data->next == data->limit);
3100 3104
3101 DeferredHandleScope deferred(isolate); 3105 DeferredHandleScope deferred(isolate);
3102 DummyVisitor visitor; 3106 DummyVisitor visitor;
3103 isolate->handle_scope_implementer()->Iterate(&visitor); 3107 isolate->handle_scope_implementer()->Iterate(&visitor);
3104 deferred.Detach(); 3108 deferred.Detach();
3105 } 3109 }
OLDNEW
« no previous file with comments | « test/cctest/test-hashing.cc ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698