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 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
773 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 773 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
774 | 774 |
775 // Fix up strings from serialized user code. | 775 // Fix up strings from serialized user code. |
776 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 776 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); |
777 | 777 |
778 Object* write_back_obj = obj; | 778 Object* write_back_obj = obj; |
779 UnalignedCopy(write_back, &write_back_obj); | 779 UnalignedCopy(write_back, &write_back_obj); |
780 #ifdef DEBUG | 780 #ifdef DEBUG |
781 if (obj->IsCode()) { | 781 if (obj->IsCode()) { |
782 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); | 782 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
| 783 #ifdef VERIFY_HEAP |
| 784 obj->ObjectVerify(); |
| 785 #endif // VERIFY_HEAP |
783 } else { | 786 } else { |
784 DCHECK(space_number != CODE_SPACE); | 787 DCHECK(space_number != CODE_SPACE); |
785 } | 788 } |
786 #endif | 789 #endif // DEBUG |
787 | |
788 if (obj->IsCode()) { | |
789 // Turn internal references encoded as offsets back to absolute addresses. | |
790 Code* code = Code::cast(obj); | |
791 Address entry = code->entry(); | |
792 int mode_mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | | |
793 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
794 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | |
795 RelocInfo* rinfo = it.rinfo(); | |
796 intptr_t offset = | |
797 reinterpret_cast<intptr_t>(rinfo->target_internal_reference()); | |
798 DCHECK(0 <= offset && offset <= code->instruction_size()); | |
799 rinfo->set_target_internal_reference(entry + offset); | |
800 } | |
801 } | |
802 } | 790 } |
803 | 791 |
804 | 792 |
805 // We know the space requirements before deserialization and can | 793 // We know the space requirements before deserialization and can |
806 // pre-allocate that reserved space. During deserialization, all we need | 794 // pre-allocate that reserved space. During deserialization, all we need |
807 // to do is to bump up the pointer for each space in the reserved | 795 // to do is to bump up the pointer for each space in the reserved |
808 // space. This is also used for fixing back references. | 796 // space. This is also used for fixing back references. |
809 // We may have to split up the pre-allocation into several chunks | 797 // We may have to split up the pre-allocation into several chunks |
810 // because it would not fit onto a single page. We do not have to keep | 798 // because it would not fit onto a single page. We do not have to keep |
811 // track of when to move to the next chunk. An opcode will signal this. | 799 // track of when to move to the next chunk. An opcode will signal this. |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 #undef CASE_BODY | 1153 #undef CASE_BODY |
1166 #undef ALL_SPACES | 1154 #undef ALL_SPACES |
1167 | 1155 |
1168 case kSkip: { | 1156 case kSkip: { |
1169 int size = source_.GetInt(); | 1157 int size = source_.GetInt(); |
1170 current = reinterpret_cast<Object**>( | 1158 current = reinterpret_cast<Object**>( |
1171 reinterpret_cast<intptr_t>(current) + size); | 1159 reinterpret_cast<intptr_t>(current) + size); |
1172 break; | 1160 break; |
1173 } | 1161 } |
1174 | 1162 |
| 1163 case kInternalReference: { |
| 1164 // Internal reference address is not encoded via skip, but by offset |
| 1165 // from code entry. |
| 1166 int pc_offset = source_.GetInt(); |
| 1167 int target_offset = source_.GetInt(); |
| 1168 Code* code = |
| 1169 Code::cast(HeapObject::FromAddress(current_object_address)); |
| 1170 DCHECK(0 <= pc_offset && pc_offset <= code->instruction_size()); |
| 1171 DCHECK(0 <= target_offset && target_offset <= code->instruction_size()); |
| 1172 Address pc = code->entry() + pc_offset; |
| 1173 Address target = code->entry() + target_offset; |
| 1174 Assembler::deserialization_set_target_internal_reference_at(pc, target); |
| 1175 break; |
| 1176 } |
| 1177 |
1175 case kNativesStringResource: { | 1178 case kNativesStringResource: { |
1176 DCHECK(!isolate_->heap()->deserialization_complete()); | 1179 DCHECK(!isolate_->heap()->deserialization_complete()); |
1177 int index = source_.Get(); | 1180 int index = source_.Get(); |
1178 Vector<const char> source_vector = Natives::GetScriptSource(index); | 1181 Vector<const char> source_vector = Natives::GetScriptSource(index); |
1179 NativesExternalStringResource* resource = | 1182 NativesExternalStringResource* resource = |
1180 new NativesExternalStringResource(source_vector.start(), | 1183 new NativesExternalStringResource(source_vector.start(), |
1181 source_vector.length()); | 1184 source_vector.length()); |
1182 Object* resource_obj = reinterpret_cast<Object*>(resource); | 1185 Object* resource_obj = reinterpret_cast<Object*>(resource); |
1183 UnalignedCopy(current++, &resource_obj); | 1186 UnalignedCopy(current++, &resource_obj); |
1184 break; | 1187 break; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1852 kCanReturnSkipInsteadOfSkipping); | 1855 kCanReturnSkipInsteadOfSkipping); |
1853 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; | 1856 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; |
1854 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); | 1857 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); |
1855 sink_->PutInt(skip, "SkipB4ExternalRef"); | 1858 sink_->PutInt(skip, "SkipB4ExternalRef"); |
1856 Address target = rinfo->target_external_reference(); | 1859 Address target = rinfo->target_external_reference(); |
1857 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); | 1860 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); |
1858 bytes_processed_so_far_ += rinfo->target_address_size(); | 1861 bytes_processed_so_far_ += rinfo->target_address_size(); |
1859 } | 1862 } |
1860 | 1863 |
1861 | 1864 |
| 1865 void Serializer::ObjectSerializer::VisitInternalReference(RelocInfo* rinfo) { |
| 1866 // We can only reference to internal references of code that has been output. |
| 1867 DCHECK(is_code_object_ && code_has_been_output_); |
| 1868 // We do not use skip from last patched pc to find the pc to patch, since |
| 1869 // target_address_address may not return addresses in ascending order when |
| 1870 // used for internal references. External references may be stored at the |
| 1871 // end of the code in the constant pool, whereas internal references are |
| 1872 // inline. That would cause the skip to be negative. Instead, we store the |
| 1873 // offset from code entry. |
| 1874 Address entry = Code::cast(object_)->entry(); |
| 1875 intptr_t pc_offset = rinfo->target_internal_reference_address() - entry; |
| 1876 intptr_t target_offset = rinfo->target_internal_reference() - entry; |
| 1877 DCHECK(0 <= pc_offset && |
| 1878 pc_offset <= Code::cast(object_)->instruction_size()); |
| 1879 DCHECK(0 <= target_offset && |
| 1880 target_offset <= Code::cast(object_)->instruction_size()); |
| 1881 sink_->Put(kInternalReference, "InternalRef"); |
| 1882 sink_->PutInt(static_cast<uintptr_t>(pc_offset), "internal ref address"); |
| 1883 sink_->PutInt(static_cast<uintptr_t>(target_offset), "internal ref value"); |
| 1884 } |
| 1885 |
| 1886 |
1862 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { | 1887 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
1863 int skip = OutputRawData(rinfo->target_address_address(), | 1888 int skip = OutputRawData(rinfo->target_address_address(), |
1864 kCanReturnSkipInsteadOfSkipping); | 1889 kCanReturnSkipInsteadOfSkipping); |
1865 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; | 1890 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; |
1866 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); | 1891 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); |
1867 sink_->PutInt(skip, "SkipB4ExternalRef"); | 1892 sink_->PutInt(skip, "SkipB4ExternalRef"); |
1868 Address target = rinfo->target_address(); | 1893 Address target = rinfo->target_address(); |
1869 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); | 1894 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); |
1870 bytes_processed_so_far_ += rinfo->target_address_size(); | 1895 bytes_processed_so_far_ += rinfo->target_address_size(); |
1871 } | 1896 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1927 } | 1952 } |
1928 | 1953 |
1929 | 1954 |
1930 Address Serializer::ObjectSerializer::PrepareCode() { | 1955 Address Serializer::ObjectSerializer::PrepareCode() { |
1931 // To make snapshots reproducible, we make a copy of the code object | 1956 // To make snapshots reproducible, we make a copy of the code object |
1932 // and wipe all pointers in the copy, which we then serialize. | 1957 // and wipe all pointers in the copy, which we then serialize. |
1933 Code* original = Code::cast(object_); | 1958 Code* original = Code::cast(object_); |
1934 Code* code = serializer_->CopyCode(original); | 1959 Code* code = serializer_->CopyCode(original); |
1935 // Code age headers are not serializable. | 1960 // Code age headers are not serializable. |
1936 code->MakeYoung(serializer_->isolate()); | 1961 code->MakeYoung(serializer_->isolate()); |
1937 Address entry = original->entry(); | |
1938 int mode_mask = RelocInfo::kCodeTargetMask | | 1962 int mode_mask = RelocInfo::kCodeTargetMask | |
1939 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 1963 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
1940 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 1964 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
1941 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | | 1965 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | |
1942 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | | 1966 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | |
1943 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 1967 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); |
1944 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 1968 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { |
1945 RelocInfo* rinfo = it.rinfo(); | 1969 RelocInfo* rinfo = it.rinfo(); |
1946 RelocInfo::Mode rmode = rinfo->rmode(); | 1970 if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) { |
1947 if (RelocInfo::IsInternalReference(rmode) || | |
1948 RelocInfo::IsInternalReferenceEncoded(rmode)) { | |
1949 // Convert internal references to relative offsets. | |
1950 Address target = rinfo->target_internal_reference(); | |
1951 intptr_t offset = target - entry; | |
1952 DCHECK(0 <= offset && offset <= original->instruction_size()); | |
1953 rinfo->set_target_internal_reference(reinterpret_cast<Address>(offset)); | |
1954 } else if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) { | |
1955 rinfo->WipeOut(); | 1971 rinfo->WipeOut(); |
1956 } | 1972 } |
1957 } | 1973 } |
1958 // We need to wipe out the header fields *after* wiping out the | 1974 // We need to wipe out the header fields *after* wiping out the |
1959 // relocations, because some of these fields are needed for the latter. | 1975 // relocations, because some of these fields are needed for the latter. |
1960 code->WipeOutHeader(); | 1976 code->WipeOutHeader(); |
1961 return code->address(); | 1977 return code->address(); |
1962 } | 1978 } |
1963 | 1979 |
1964 | 1980 |
1965 int Serializer::ObjectSerializer::OutputRawData( | 1981 int Serializer::ObjectSerializer::OutputRawData( |
1966 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { | 1982 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { |
1967 Address object_start = object_->address(); | 1983 Address object_start = object_->address(); |
1968 int base = bytes_processed_so_far_; | 1984 int base = bytes_processed_so_far_; |
1969 int up_to_offset = static_cast<int>(up_to - object_start); | 1985 int up_to_offset = static_cast<int>(up_to - object_start); |
1970 int to_skip = up_to_offset - bytes_processed_so_far_; | 1986 int to_skip = up_to_offset - bytes_processed_so_far_; |
1971 int bytes_to_output = to_skip; | 1987 int bytes_to_output = to_skip; |
1972 bytes_processed_so_far_ += to_skip; | 1988 bytes_processed_so_far_ += to_skip; |
1973 // This assert will fail if the reloc info gives us the target_address_address | 1989 // This assert will fail if the reloc info gives us the target_address_address |
1974 // locations in a non-ascending order. Luckily that doesn't happen. | 1990 // locations in a non-ascending order. Luckily that doesn't happen. |
1975 DCHECK(to_skip >= 0); | 1991 DCHECK(to_skip >= 0); |
1976 bool outputting_code = false; | 1992 bool outputting_code = false; |
1977 if (to_skip != 0 && code_object_ && !code_has_been_output_) { | 1993 if (to_skip != 0 && is_code_object_ && !code_has_been_output_) { |
1978 // Output the code all at once and fix later. | 1994 // Output the code all at once and fix later. |
1979 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; | 1995 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; |
1980 outputting_code = true; | 1996 outputting_code = true; |
1981 code_has_been_output_ = true; | 1997 code_has_been_output_ = true; |
1982 } | 1998 } |
1983 if (bytes_to_output != 0 && | 1999 if (bytes_to_output != 0 && (!is_code_object_ || outputting_code)) { |
1984 (!code_object_ || outputting_code)) { | |
1985 #define RAW_CASE(index) \ | 2000 #define RAW_CASE(index) \ |
1986 if (!outputting_code && bytes_to_output == index * kPointerSize && \ | 2001 if (!outputting_code && bytes_to_output == index * kPointerSize && \ |
1987 index * kPointerSize == to_skip) { \ | 2002 index * kPointerSize == to_skip) { \ |
1988 sink_->PutSection(kRawData + index, "RawDataFixed"); \ | 2003 sink_->PutSection(kRawData + index, "RawDataFixed"); \ |
1989 to_skip = 0; /* This insn already skips. */ \ | 2004 to_skip = 0; /* This insn already skips. */ \ |
1990 } else /* NOLINT */ | 2005 } else /* NOLINT */ |
1991 COMMON_RAW_LENGTHS(RAW_CASE) | 2006 COMMON_RAW_LENGTHS(RAW_CASE) |
1992 #undef RAW_CASE | 2007 #undef RAW_CASE |
1993 { /* NOLINT */ | 2008 { /* NOLINT */ |
1994 // We always end up here if we are outputting the code of a code object. | 2009 // We always end up here if we are outputting the code of a code object. |
1995 sink_->Put(kRawData, "RawData"); | 2010 sink_->Put(kRawData, "RawData"); |
1996 sink_->PutInt(bytes_to_output, "length"); | 2011 sink_->PutInt(bytes_to_output, "length"); |
1997 } | 2012 } |
1998 | 2013 |
1999 if (code_object_) object_start = PrepareCode(); | 2014 if (is_code_object_) object_start = PrepareCode(); |
2000 | 2015 |
2001 const char* description = code_object_ ? "Code" : "Byte"; | 2016 const char* description = is_code_object_ ? "Code" : "Byte"; |
2002 #ifdef MEMORY_SANITIZER | 2017 #ifdef MEMORY_SANITIZER |
2003 // Object sizes are usually rounded up with uninitialized padding space. | 2018 // Object sizes are usually rounded up with uninitialized padding space. |
2004 MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output); | 2019 MSAN_MEMORY_IS_INITIALIZED(object_start + base, bytes_to_output); |
2005 #endif // MEMORY_SANITIZER | 2020 #endif // MEMORY_SANITIZER |
2006 sink_->PutRaw(object_start + base, bytes_to_output, description); | 2021 sink_->PutRaw(object_start + base, bytes_to_output, description); |
2007 } | 2022 } |
2008 if (to_skip != 0 && return_skip == kIgnoringReturn) { | 2023 if (to_skip != 0 && return_skip == kIgnoringReturn) { |
2009 sink_->Put(kSkip, "Skip"); | 2024 sink_->Put(kSkip, "Skip"); |
2010 sink_->PutInt(to_skip, "SkipDistance"); | 2025 sink_->PutInt(to_skip, "SkipDistance"); |
2011 to_skip = 0; | 2026 to_skip = 0; |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2315 if (isolate->logger()->is_logging_code_events() || | 2330 if (isolate->logger()->is_logging_code_events() || |
2316 isolate->cpu_profiler()->is_profiling()) { | 2331 isolate->cpu_profiler()->is_profiling()) { |
2317 String* name = isolate->heap()->empty_string(); | 2332 String* name = isolate->heap()->empty_string(); |
2318 if (result->script()->IsScript()) { | 2333 if (result->script()->IsScript()) { |
2319 Script* script = Script::cast(result->script()); | 2334 Script* script = Script::cast(result->script()); |
2320 if (script->name()->IsString()) name = String::cast(script->name()); | 2335 if (script->name()->IsString()) name = String::cast(script->name()); |
2321 } | 2336 } |
2322 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), | 2337 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), |
2323 *result, NULL, name); | 2338 *result, NULL, name); |
2324 } | 2339 } |
2325 | |
2326 return scope.CloseAndEscape(result); | 2340 return scope.CloseAndEscape(result); |
2327 } | 2341 } |
2328 | 2342 |
2329 | 2343 |
2330 void SerializedData::AllocateData(int size) { | 2344 void SerializedData::AllocateData(int size) { |
2331 DCHECK(!owns_data_); | 2345 DCHECK(!owns_data_); |
2332 data_ = NewArray<byte>(size); | 2346 data_ = NewArray<byte>(size); |
2333 size_ = size; | 2347 size_ = size; |
2334 owns_data_ = true; | 2348 owns_data_ = true; |
2335 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); | 2349 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2547 DisallowHeapAllocation no_gc; | 2561 DisallowHeapAllocation no_gc; |
2548 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2562 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2549 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2563 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2550 if (r == CHECK_SUCCESS) return scd; | 2564 if (r == CHECK_SUCCESS) return scd; |
2551 cached_data->Reject(); | 2565 cached_data->Reject(); |
2552 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2566 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2553 delete scd; | 2567 delete scd; |
2554 return NULL; | 2568 return NULL; |
2555 } | 2569 } |
2556 } } // namespace v8::internal | 2570 } } // namespace v8::internal |
OLD | NEW |