| 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 |