Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 1805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1816 base::ElapsedTimer timer; | 1816 base::ElapsedTimer timer; |
| 1817 if (FLAG_profile_deserialization) timer.Start(); | 1817 if (FLAG_profile_deserialization) timer.Start(); |
| 1818 | 1818 |
| 1819 // Serialize code object. | 1819 // Serialize code object. |
| 1820 List<byte> payload; | 1820 List<byte> payload; |
| 1821 ListSnapshotSink list_sink(&payload); | 1821 ListSnapshotSink list_sink(&payload); |
| 1822 DebugSnapshotSink debug_sink(&list_sink); | 1822 DebugSnapshotSink debug_sink(&list_sink); |
| 1823 SnapshotByteSink* sink = FLAG_trace_code_serializer | 1823 SnapshotByteSink* sink = FLAG_trace_code_serializer |
| 1824 ? static_cast<SnapshotByteSink*>(&debug_sink) | 1824 ? static_cast<SnapshotByteSink*>(&debug_sink) |
| 1825 : static_cast<SnapshotByteSink*>(&list_sink); | 1825 : static_cast<SnapshotByteSink*>(&list_sink); |
| 1826 CodeSerializer cs(isolate, sink, *source); | 1826 CodeSerializer cs(isolate, sink, *source, info->code()); |
| 1827 DisallowHeapAllocation no_gc; | 1827 DisallowHeapAllocation no_gc; |
| 1828 Object** location = Handle<Object>::cast(info).location(); | 1828 Object** location = Handle<Object>::cast(info).location(); |
| 1829 cs.VisitPointer(location); | 1829 cs.VisitPointer(location); |
| 1830 cs.Pad(); | 1830 cs.Pad(); |
| 1831 | 1831 |
| 1832 SerializedCodeData data(&payload, &cs); | 1832 SerializedCodeData data(&payload, &cs); |
| 1833 ScriptData* script_data = data.GetScriptData(); | 1833 ScriptData* script_data = data.GetScriptData(); |
| 1834 | 1834 |
| 1835 if (FLAG_profile_deserialization) { | 1835 if (FLAG_profile_deserialization) { |
| 1836 double ms = timer.Elapsed().InMillisecondsF(); | 1836 double ms = timer.Elapsed().InMillisecondsF(); |
| 1837 int length = script_data->length(); | 1837 int length = script_data->length(); |
| 1838 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); | 1838 PrintF("[Serializing to %d bytes took %0.3f ms]\n", length, ms); |
| 1839 } | 1839 } |
| 1840 | 1840 |
| 1841 return script_data; | 1841 return script_data; |
| 1842 } | 1842 } |
| 1843 | 1843 |
| 1844 | 1844 |
| 1845 void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, | 1845 void CodeSerializer::SerializeObject(Object* o, HowToCode how_to_code, |
| 1846 WhereToPoint where_to_point, int skip) { | 1846 WhereToPoint where_to_point, int skip) { |
| 1847 CHECK(o->IsHeapObject()); | |
| 1848 HeapObject* heap_object = HeapObject::cast(o); | 1847 HeapObject* heap_object = HeapObject::cast(o); |
| 1849 | 1848 |
| 1850 // The code-caches link to context-specific code objects, which | |
| 1851 // the startup and context serializes cannot currently handle. | |
| 1852 DCHECK(!heap_object->IsMap() || | |
| 1853 Map::cast(heap_object)->code_cache() == | |
| 1854 heap_object->GetHeap()->empty_fixed_array()); | |
| 1855 | |
| 1856 int root_index; | 1849 int root_index; |
| 1857 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { | 1850 if ((root_index = RootIndex(heap_object, how_to_code)) != kInvalidRootIndex) { |
| 1858 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); | 1851 PutRoot(root_index, heap_object, how_to_code, where_to_point, skip); |
| 1859 return; | 1852 return; |
| 1860 } | 1853 } |
| 1861 | 1854 |
| 1862 // TODO(yangguo) wire up global object. | |
| 1863 // TODO(yangguo) We cannot deal with different hash seeds yet. | |
| 1864 DCHECK(!heap_object->IsHashTable()); | |
| 1865 | |
| 1866 if (address_mapper_.IsMapped(heap_object)) { | 1855 if (address_mapper_.IsMapped(heap_object)) { |
| 1867 SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, | 1856 SerializeReferenceToPreviousObject(heap_object, how_to_code, where_to_point, |
| 1868 skip); | 1857 skip); |
| 1869 return; | 1858 return; |
| 1870 } | 1859 } |
| 1871 | 1860 |
| 1861 if (skip != 0) { | |
| 1862 sink_->Put(kSkip, "SkipFromSerializeObject"); | |
| 1863 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | |
| 1864 } | |
| 1865 | |
| 1872 if (heap_object->IsCode()) { | 1866 if (heap_object->IsCode()) { |
| 1873 Code* code_object = Code::cast(heap_object); | 1867 Code* code_object = Code::cast(heap_object); |
| 1874 switch (code_object->kind()) { | 1868 switch (code_object->kind()) { |
| 1875 case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet. | 1869 case Code::OPTIMIZED_FUNCTION: // No optimized code compiled yet. |
| 1876 case Code::HANDLER: // No handlers patched in yet. | 1870 case Code::HANDLER: // No handlers patched in yet. |
| 1877 case Code::REGEXP: // No regexp literals initialized yet. | 1871 case Code::REGEXP: // No regexp literals initialized yet. |
| 1878 case Code::NUMBER_OF_KINDS: // Pseudo enum value. | 1872 case Code::NUMBER_OF_KINDS: // Pseudo enum value. |
| 1879 CHECK(false); | 1873 CHECK(false); |
| 1880 case Code::BUILTIN: | 1874 case Code::BUILTIN: |
| 1881 SerializeBuiltin(code_object, how_to_code, where_to_point, skip); | 1875 SerializeBuiltin(code_object, how_to_code, where_to_point); |
| 1882 return; | 1876 return; |
| 1883 case Code::STUB: | 1877 case Code::STUB: |
| 1884 SerializeCodeStub(code_object, how_to_code, where_to_point, skip); | 1878 SerializeCodeStub(code_object, how_to_code, where_to_point); |
| 1885 return; | 1879 return; |
| 1886 #define IC_KIND_CASE(KIND) case Code::KIND: | 1880 #define IC_KIND_CASE(KIND) case Code::KIND: |
| 1887 IC_KIND_LIST(IC_KIND_CASE) | 1881 IC_KIND_LIST(IC_KIND_CASE) |
| 1888 #undef IC_KIND_CASE | 1882 #undef IC_KIND_CASE |
| 1883 SerializeHeapObject(code_object, how_to_code, where_to_point); | |
| 1884 return; | |
| 1889 case Code::FUNCTION: | 1885 case Code::FUNCTION: |
| 1890 SerializeHeapObject(code_object, how_to_code, where_to_point, skip); | 1886 // Only serialize the code for the toplevel function. Replace code |
| 1887 // of included function literals by the lazy compile builtin. | |
| 1888 // This is safe, as checked in Compiler::BuildFunctionInfo. | |
| 1889 if (code_object != main_code_) { | |
| 1890 Code* lazy = *isolate()->builtins()->CompileLazy(); | |
| 1891 SerializeBuiltin(lazy, how_to_code, where_to_point); | |
| 1892 } else { | |
| 1893 SerializeHeapObject(code_object, how_to_code, where_to_point); | |
| 1894 } | |
| 1891 return; | 1895 return; |
| 1892 } | 1896 } |
| 1893 } | 1897 } |
| 1894 | 1898 |
| 1895 if (heap_object == source_) { | 1899 if (heap_object == source_) { |
| 1896 SerializeSourceObject(how_to_code, where_to_point, skip); | 1900 SerializeSourceObject(how_to_code, where_to_point); |
| 1897 return; | 1901 return; |
| 1898 } | 1902 } |
| 1899 | 1903 |
| 1900 SerializeHeapObject(heap_object, how_to_code, where_to_point, skip); | 1904 // Past this point we should not see any (context-specific) maps anymore. |
|
mvstanton
2014/09/26 12:28:49
Nice checks here.
| |
| 1905 CHECK(!heap_object->IsMap()); | |
| 1906 // There should be no references to the global object embedded. | |
| 1907 CHECK(!heap_object->IsJSGlobalProxy() && !heap_object->IsGlobalObject()); | |
| 1908 // There should be no hash table embedded. They would require rehashing. | |
| 1909 CHECK(!heap_object->IsHashTable()); | |
| 1910 | |
| 1911 SerializeHeapObject(heap_object, how_to_code, where_to_point); | |
| 1901 } | 1912 } |
| 1902 | 1913 |
| 1903 | 1914 |
| 1904 void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, | 1915 void CodeSerializer::SerializeHeapObject(HeapObject* heap_object, |
| 1905 HowToCode how_to_code, | 1916 HowToCode how_to_code, |
| 1906 WhereToPoint where_to_point, | 1917 WhereToPoint where_to_point) { |
| 1907 int skip) { | |
| 1908 if (heap_object->IsScript()) { | 1918 if (heap_object->IsScript()) { |
| 1909 // The wrapper cache uses a Foreign object to point to a global handle. | 1919 // The wrapper cache uses a Foreign object to point to a global handle. |
| 1910 // However, the object visitor expects foreign objects to point to external | 1920 // However, the object visitor expects foreign objects to point to external |
| 1911 // references. Clear the cache to avoid this issue. | 1921 // references. Clear the cache to avoid this issue. |
| 1912 Script::cast(heap_object)->ClearWrapperCache(); | 1922 Script::cast(heap_object)->ClearWrapperCache(); |
| 1913 } | 1923 } |
| 1914 | 1924 |
| 1915 if (skip != 0) { | |
| 1916 sink_->Put(kSkip, "SkipFromSerializeObject"); | |
| 1917 sink_->PutInt(skip, "SkipDistanceFromSerializeObject"); | |
| 1918 } | |
| 1919 | |
| 1920 if (FLAG_trace_code_serializer) { | 1925 if (FLAG_trace_code_serializer) { |
| 1921 PrintF("Encoding heap object: "); | 1926 PrintF("Encoding heap object: "); |
| 1922 heap_object->ShortPrint(); | 1927 heap_object->ShortPrint(); |
| 1923 PrintF("\n"); | 1928 PrintF("\n"); |
| 1924 } | 1929 } |
| 1925 | 1930 |
| 1926 // Object has not yet been serialized. Serialize it here. | 1931 // Object has not yet been serialized. Serialize it here. |
| 1927 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, | 1932 ObjectSerializer serializer(this, heap_object, sink_, how_to_code, |
| 1928 where_to_point); | 1933 where_to_point); |
| 1929 serializer.Serialize(); | 1934 serializer.Serialize(); |
| 1930 } | 1935 } |
| 1931 | 1936 |
| 1932 | 1937 |
| 1933 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, | 1938 void CodeSerializer::SerializeBuiltin(Code* builtin, HowToCode how_to_code, |
| 1934 WhereToPoint where_to_point, int skip) { | 1939 WhereToPoint where_to_point) { |
| 1935 if (skip != 0) { | |
| 1936 sink_->Put(kSkip, "SkipFromSerializeBuiltin"); | |
| 1937 sink_->PutInt(skip, "SkipDistanceFromSerializeBuiltin"); | |
| 1938 } | |
| 1939 | |
| 1940 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || | 1940 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 1941 (how_to_code == kPlain && where_to_point == kInnerPointer) || | 1941 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
| 1942 (how_to_code == kFromCode && where_to_point == kInnerPointer)); | 1942 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 1943 int builtin_index = builtin->builtin_index(); | 1943 int builtin_index = builtin->builtin_index(); |
| 1944 DCHECK_LT(builtin_index, Builtins::builtin_count); | 1944 DCHECK_LT(builtin_index, Builtins::builtin_count); |
| 1945 DCHECK_LE(0, builtin_index); | 1945 DCHECK_LE(0, builtin_index); |
| 1946 | 1946 |
| 1947 if (FLAG_trace_code_serializer) { | 1947 if (FLAG_trace_code_serializer) { |
| 1948 PrintF("Encoding builtin: %s\n", | 1948 PrintF("Encoding builtin: %s\n", |
| 1949 isolate()->builtins()->name(builtin_index)); | 1949 isolate()->builtins()->name(builtin_index)); |
| 1950 } | 1950 } |
| 1951 | 1951 |
| 1952 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); | 1952 sink_->Put(kBuiltin + how_to_code + where_to_point, "Builtin"); |
| 1953 sink_->PutInt(builtin_index, "builtin_index"); | 1953 sink_->PutInt(builtin_index, "builtin_index"); |
| 1954 } | 1954 } |
| 1955 | 1955 |
| 1956 | 1956 |
| 1957 void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code, | 1957 void CodeSerializer::SerializeCodeStub(Code* stub, HowToCode how_to_code, |
| 1958 WhereToPoint where_to_point, int skip) { | 1958 WhereToPoint where_to_point) { |
| 1959 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || | 1959 DCHECK((how_to_code == kPlain && where_to_point == kStartOfObject) || |
| 1960 (how_to_code == kPlain && where_to_point == kInnerPointer) || | 1960 (how_to_code == kPlain && where_to_point == kInnerPointer) || |
| 1961 (how_to_code == kFromCode && where_to_point == kInnerPointer)); | 1961 (how_to_code == kFromCode && where_to_point == kInnerPointer)); |
| 1962 uint32_t stub_key = stub->stub_key(); | 1962 uint32_t stub_key = stub->stub_key(); |
| 1963 DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); | 1963 DCHECK(CodeStub::MajorKeyFromKey(stub_key) != CodeStub::NoCache); |
| 1964 | 1964 |
| 1965 if (skip != 0) { | |
| 1966 sink_->Put(kSkip, "SkipFromSerializeCodeStub"); | |
| 1967 sink_->PutInt(skip, "SkipDistanceFromSerializeCodeStub"); | |
| 1968 } | |
| 1969 | |
| 1970 int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; | 1965 int index = AddCodeStubKey(stub_key) + kCodeStubsBaseIndex; |
| 1971 | 1966 |
| 1972 if (FLAG_trace_code_serializer) { | 1967 if (FLAG_trace_code_serializer) { |
| 1973 PrintF("Encoding code stub %s as %d\n", | 1968 PrintF("Encoding code stub %s as %d\n", |
| 1974 CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), | 1969 CodeStub::MajorName(CodeStub::MajorKeyFromKey(stub_key), false), |
| 1975 index); | 1970 index); |
| 1976 } | 1971 } |
| 1977 | 1972 |
| 1978 sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); | 1973 sink_->Put(kAttachedReference + how_to_code + where_to_point, "CodeStub"); |
| 1979 sink_->PutInt(index, "CodeStub key"); | 1974 sink_->PutInt(index, "CodeStub key"); |
| 1980 } | 1975 } |
| 1981 | 1976 |
| 1982 | 1977 |
| 1983 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { | 1978 int CodeSerializer::AddCodeStubKey(uint32_t stub_key) { |
| 1984 // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2). | 1979 // TODO(yangguo) Maybe we need a hash table for a faster lookup than O(n^2). |
| 1985 int index = 0; | 1980 int index = 0; |
| 1986 while (index < stub_keys_.length()) { | 1981 while (index < stub_keys_.length()) { |
| 1987 if (stub_keys_[index] == stub_key) return index; | 1982 if (stub_keys_[index] == stub_key) return index; |
| 1988 index++; | 1983 index++; |
| 1989 } | 1984 } |
| 1990 stub_keys_.Add(stub_key); | 1985 stub_keys_.Add(stub_key); |
| 1991 return index; | 1986 return index; |
| 1992 } | 1987 } |
| 1993 | 1988 |
| 1994 | 1989 |
| 1995 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, | 1990 void CodeSerializer::SerializeSourceObject(HowToCode how_to_code, |
| 1996 WhereToPoint where_to_point, | 1991 WhereToPoint where_to_point) { |
| 1997 int skip) { | 1992 if (FLAG_trace_code_serializer) PrintF("Encoding source object\n"); |
| 1998 if (skip != 0) { | |
| 1999 sink_->Put(kSkip, "SkipFromSerializeSourceObject"); | |
| 2000 sink_->PutInt(skip, "SkipDistanceFromSerializeSourceObject"); | |
| 2001 } | |
| 2002 | |
| 2003 if (FLAG_trace_code_serializer) { | |
| 2004 PrintF("Encoding source object\n"); | |
| 2005 } | |
| 2006 | 1993 |
| 2007 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); | 1994 DCHECK(how_to_code == kPlain && where_to_point == kStartOfObject); |
| 2008 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); | 1995 sink_->Put(kAttachedReference + how_to_code + where_to_point, "Source"); |
| 2009 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); | 1996 sink_->PutInt(kSourceObjectIndex, "kSourceObjectIndex"); |
| 2010 } | 1997 } |
| 2011 | 1998 |
| 2012 | 1999 |
| 2013 Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, | 2000 Handle<SharedFunctionInfo> CodeSerializer::Deserialize(Isolate* isolate, |
| 2014 ScriptData* data, | 2001 ScriptData* data, |
| 2015 Handle<String> source) { | 2002 Handle<String> source) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2099 | 2086 |
| 2100 int SerializedCodeData::CheckSum(String* string) { | 2087 int SerializedCodeData::CheckSum(String* string) { |
| 2101 int checksum = Version::Hash(); | 2088 int checksum = Version::Hash(); |
| 2102 #ifdef DEBUG | 2089 #ifdef DEBUG |
| 2103 uint32_t seed = static_cast<uint32_t>(checksum); | 2090 uint32_t seed = static_cast<uint32_t>(checksum); |
| 2104 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); | 2091 checksum = static_cast<int>(IteratingStringHasher::Hash(string, seed)); |
| 2105 #endif // DEBUG | 2092 #endif // DEBUG |
| 2106 return checksum; | 2093 return checksum; |
| 2107 } | 2094 } |
| 2108 } } // namespace v8::internal | 2095 } } // namespace v8::internal |
| OLD | NEW |