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 |