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 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); | 781 if (obj->IsAllocationSite()) RelinkAllocationSite(AllocationSite::cast(obj)); |
782 | 782 |
783 // Fix up strings from serialized user code. | 783 // Fix up strings from serialized user code. |
784 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); | 784 if (deserializing_user_code()) obj = ProcessNewObjectFromSerializedCode(obj); |
785 | 785 |
786 Object* write_back_obj = obj; | 786 Object* write_back_obj = obj; |
787 UnalignedCopy(write_back, &write_back_obj); | 787 UnalignedCopy(write_back, &write_back_obj); |
788 #ifdef DEBUG | 788 #ifdef DEBUG |
789 if (obj->IsCode()) { | 789 if (obj->IsCode()) { |
790 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); | 790 DCHECK(space_number == CODE_SPACE || space_number == LO_SPACE); |
791 #ifdef VERIFY_HEAP | |
792 obj->ObjectVerify(); | |
793 #endif // VERIFY_HEAP | |
791 } else { | 794 } else { |
792 DCHECK(space_number != CODE_SPACE); | 795 DCHECK(space_number != CODE_SPACE); |
793 } | 796 } |
794 #endif | 797 #endif // DEBUG |
795 | |
796 if (obj->IsCode()) { | |
797 // Turn internal references encoded as offsets back to absolute addresses. | |
798 Code* code = Code::cast(obj); | |
799 Address entry = code->entry(); | |
800 int mode_mask = RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | | |
801 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); | |
802 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | |
803 RelocInfo* rinfo = it.rinfo(); | |
804 intptr_t offset = | |
805 reinterpret_cast<intptr_t>(rinfo->target_internal_reference()); | |
806 DCHECK(0 <= offset && offset <= code->instruction_size()); | |
807 rinfo->set_target_internal_reference(entry + offset); | |
808 } | |
809 } | |
810 } | 798 } |
811 | 799 |
812 | 800 |
813 // We know the space requirements before deserialization and can | 801 // We know the space requirements before deserialization and can |
814 // pre-allocate that reserved space. During deserialization, all we need | 802 // pre-allocate that reserved space. During deserialization, all we need |
815 // to do is to bump up the pointer for each space in the reserved | 803 // to do is to bump up the pointer for each space in the reserved |
816 // space. This is also used for fixing back references. | 804 // space. This is also used for fixing back references. |
817 // We may have to split up the pre-allocation into several chunks | 805 // We may have to split up the pre-allocation into several chunks |
818 // because it would not fit onto a single page. We do not have to keep | 806 // because it would not fit onto a single page. We do not have to keep |
819 // track of when to move to the next chunk. An opcode will signal this. | 807 // track of when to move to the next chunk. An opcode will signal this. |
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1178 #undef CASE_BODY | 1166 #undef CASE_BODY |
1179 #undef ALL_SPACES | 1167 #undef ALL_SPACES |
1180 | 1168 |
1181 case kSkip: { | 1169 case kSkip: { |
1182 int size = source_.GetInt(); | 1170 int size = source_.GetInt(); |
1183 current = reinterpret_cast<Object**>( | 1171 current = reinterpret_cast<Object**>( |
1184 reinterpret_cast<intptr_t>(current) + size); | 1172 reinterpret_cast<intptr_t>(current) + size); |
1185 break; | 1173 break; |
1186 } | 1174 } |
1187 | 1175 |
1176 case kInternalReference: { | |
1177 // Internal reference address is not encoded via skip, but by offset | |
1178 // from code entry. | |
1179 int pc_offset = source_.GetInt(); | |
1180 int target_offset = source_.GetInt(); | |
1181 Code* code = | |
1182 Code::cast(HeapObject::FromAddress(current_object_address)); | |
1183 DCHECK(0 <= pc_offset && pc_offset <= code->instruction_size()); | |
1184 DCHECK(0 <= target_offset && target_offset <= code->instruction_size()); | |
1185 Address pc = code->entry() + pc_offset; | |
1186 Address target = code->entry() + target_offset; | |
1187 Assembler::deserialization_set_target_internal_reference_at(pc, target); | |
1188 break; | |
1189 } | |
1190 | |
1188 case kNativesStringResource: { | 1191 case kNativesStringResource: { |
1189 DCHECK(!isolate_->heap()->deserialization_complete()); | 1192 DCHECK(!isolate_->heap()->deserialization_complete()); |
1190 int index = source_.Get(); | 1193 int index = source_.Get(); |
1191 Vector<const char> source_vector = Natives::GetScriptSource(index); | 1194 Vector<const char> source_vector = Natives::GetScriptSource(index); |
1192 NativesExternalStringResource* resource = | 1195 NativesExternalStringResource* resource = |
1193 new NativesExternalStringResource(source_vector.start(), | 1196 new NativesExternalStringResource(source_vector.start(), |
1194 source_vector.length()); | 1197 source_vector.length()); |
1195 Object* resource_obj = reinterpret_cast<Object*>(resource); | 1198 Object* resource_obj = reinterpret_cast<Object*>(resource); |
1196 UnalignedCopy(current++, &resource_obj); | 1199 UnalignedCopy(current++, &resource_obj); |
1197 break; | 1200 break; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1865 kCanReturnSkipInsteadOfSkipping); | 1868 kCanReturnSkipInsteadOfSkipping); |
1866 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; | 1869 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; |
1867 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); | 1870 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); |
1868 sink_->PutInt(skip, "SkipB4ExternalRef"); | 1871 sink_->PutInt(skip, "SkipB4ExternalRef"); |
1869 Address target = rinfo->target_external_reference(); | 1872 Address target = rinfo->target_external_reference(); |
1870 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); | 1873 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); |
1871 bytes_processed_so_far_ += rinfo->target_address_size(); | 1874 bytes_processed_so_far_ += rinfo->target_address_size(); |
1872 } | 1875 } |
1873 | 1876 |
1874 | 1877 |
1878 void Serializer::ObjectSerializer::VisitInternalReference(RelocInfo* rinfo) { | |
1879 DCHECK(code_object_ && code_has_been_output_); | |
1880 // We do not use skip from last patched pc to find the pc to patch, since | |
1881 // target_address_address may not return addresses in ascending order when | |
1882 // used for internal references. External references may be stored at the | |
1883 // end of the code in the constant pool, whereas internal references are | |
1884 // inline. That would cause the skip to be negative. Instead, we store the | |
1885 // offset from code entry. | |
1886 Address entry = Code::cast(object_)->entry(); | |
1887 intptr_t pc_offset = rinfo->target_internal_reference_address() - entry; | |
1888 intptr_t target_offset = rinfo->target_internal_reference() - entry; | |
1889 DCHECK(0 <= pc_offset && | |
1890 pc_offset <= Code::cast(object_)->instruction_size()); | |
1891 DCHECK(0 <= target_offset && | |
1892 target_offset <= Code::cast(object_)->instruction_size()); | |
1893 sink_->Put(kInternalReference, "InternalRef"); | |
1894 sink_->PutInt(static_cast<uintptr_t>(pc_offset), "internal ref address"); | |
1895 sink_->PutInt(static_cast<uintptr_t>(target_offset), "internal ref value"); | |
1896 } | |
1897 | |
1898 | |
1875 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { | 1899 void Serializer::ObjectSerializer::VisitRuntimeEntry(RelocInfo* rinfo) { |
1876 int skip = OutputRawData(rinfo->target_address_address(), | 1900 int skip = OutputRawData(rinfo->target_address_address(), |
1877 kCanReturnSkipInsteadOfSkipping); | 1901 kCanReturnSkipInsteadOfSkipping); |
1878 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; | 1902 HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain; |
1879 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); | 1903 sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); |
1880 sink_->PutInt(skip, "SkipB4ExternalRef"); | 1904 sink_->PutInt(skip, "SkipB4ExternalRef"); |
1881 Address target = rinfo->target_address(); | 1905 Address target = rinfo->target_address(); |
1882 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); | 1906 sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); |
1883 bytes_processed_so_far_ += rinfo->target_address_size(); | 1907 bytes_processed_so_far_ += rinfo->target_address_size(); |
1884 } | 1908 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1940 } | 1964 } |
1941 | 1965 |
1942 | 1966 |
1943 Address Serializer::ObjectSerializer::PrepareCode() { | 1967 Address Serializer::ObjectSerializer::PrepareCode() { |
1944 // To make snapshots reproducible, we make a copy of the code object | 1968 // To make snapshots reproducible, we make a copy of the code object |
1945 // and wipe all pointers in the copy, which we then serialize. | 1969 // and wipe all pointers in the copy, which we then serialize. |
1946 Code* original = Code::cast(object_); | 1970 Code* original = Code::cast(object_); |
1947 Code* code = serializer_->CopyCode(original); | 1971 Code* code = serializer_->CopyCode(original); |
1948 // Code age headers are not serializable. | 1972 // Code age headers are not serializable. |
1949 code->MakeYoung(serializer_->isolate()); | 1973 code->MakeYoung(serializer_->isolate()); |
1950 Address entry = original->entry(); | |
1951 int mode_mask = RelocInfo::kCodeTargetMask | | 1974 int mode_mask = RelocInfo::kCodeTargetMask | |
1952 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 1975 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
1953 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | | 1976 RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | |
1954 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | | 1977 RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) | |
1955 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | | 1978 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | |
1956 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); | 1979 RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); |
1957 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { | 1980 for (RelocIterator it(code, mode_mask); !it.done(); it.next()) { |
1958 RelocInfo* rinfo = it.rinfo(); | 1981 RelocInfo* rinfo = it.rinfo(); |
1959 RelocInfo::Mode rmode = rinfo->rmode(); | 1982 if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) { |
1960 if (RelocInfo::IsInternalReference(rmode) || | |
1961 RelocInfo::IsInternalReferenceEncoded(rmode)) { | |
1962 // Convert internal references to relative offsets. | |
1963 Address target = rinfo->target_internal_reference(); | |
1964 intptr_t offset = target - entry; | |
1965 DCHECK(0 <= offset && offset <= original->instruction_size()); | |
1966 rinfo->set_target_internal_reference(reinterpret_cast<Address>(offset)); | |
1967 } else if (!(FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool())) { | |
1968 rinfo->WipeOut(); | 1983 rinfo->WipeOut(); |
1969 } | 1984 } |
1970 } | 1985 } |
1971 // We need to wipe out the header fields *after* wiping out the | 1986 // We need to wipe out the header fields *after* wiping out the |
1972 // relocations, because some of these fields are needed for the latter. | 1987 // relocations, because some of these fields are needed for the latter. |
1973 code->WipeOutHeader(); | 1988 code->WipeOutHeader(); |
1974 return code->address(); | 1989 return code->address(); |
1975 } | 1990 } |
1976 | 1991 |
1977 | 1992 |
1978 int Serializer::ObjectSerializer::OutputRawData( | 1993 int Serializer::ObjectSerializer::OutputRawData( |
1979 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { | 1994 Address up_to, Serializer::ObjectSerializer::ReturnSkip return_skip) { |
1980 Address object_start = object_->address(); | 1995 Address object_start = object_->address(); |
1981 int base = bytes_processed_so_far_; | 1996 int base = bytes_processed_so_far_; |
1982 int up_to_offset = static_cast<int>(up_to - object_start); | 1997 int up_to_offset = static_cast<int>(up_to - object_start); |
1983 int to_skip = up_to_offset - bytes_processed_so_far_; | 1998 int to_skip = up_to_offset - bytes_processed_so_far_; |
1984 int bytes_to_output = to_skip; | 1999 int bytes_to_output = to_skip; |
1985 bytes_processed_so_far_ += to_skip; | 2000 bytes_processed_so_far_ += to_skip; |
1986 // This assert will fail if the reloc info gives us the target_address_address | 2001 // This assert will fail if the reloc info gives us the target_address_address |
1987 // locations in a non-ascending order. Luckily that doesn't happen. | 2002 // locations in a non-ascending order. Luckily that doesn't happen. |
1988 DCHECK(to_skip >= 0); | 2003 DCHECK(to_skip >= 0); |
Yang
2015/03/18 09:25:49
This is the assertion I was referring to.
| |
1989 bool outputting_code = false; | 2004 bool outputting_code = false; |
1990 if (to_skip != 0 && code_object_ && !code_has_been_output_) { | 2005 if (to_skip != 0 && code_object_ && !code_has_been_output_) { |
1991 // Output the code all at once and fix later. | 2006 // Output the code all at once and fix later. |
1992 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; | 2007 bytes_to_output = object_->Size() + to_skip - bytes_processed_so_far_; |
1993 outputting_code = true; | 2008 outputting_code = true; |
1994 code_has_been_output_ = true; | 2009 code_has_been_output_ = true; |
1995 } | 2010 } |
1996 if (bytes_to_output != 0 && | 2011 if (bytes_to_output != 0 && |
1997 (!code_object_ || outputting_code)) { | 2012 (!code_object_ || outputting_code)) { |
1998 #define RAW_CASE(index) \ | 2013 #define RAW_CASE(index) \ |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2328 if (isolate->logger()->is_logging_code_events() || | 2343 if (isolate->logger()->is_logging_code_events() || |
2329 isolate->cpu_profiler()->is_profiling()) { | 2344 isolate->cpu_profiler()->is_profiling()) { |
2330 String* name = isolate->heap()->empty_string(); | 2345 String* name = isolate->heap()->empty_string(); |
2331 if (result->script()->IsScript()) { | 2346 if (result->script()->IsScript()) { |
2332 Script* script = Script::cast(result->script()); | 2347 Script* script = Script::cast(result->script()); |
2333 if (script->name()->IsString()) name = String::cast(script->name()); | 2348 if (script->name()->IsString()) name = String::cast(script->name()); |
2334 } | 2349 } |
2335 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), | 2350 isolate->logger()->CodeCreateEvent(Logger::SCRIPT_TAG, result->code(), |
2336 *result, NULL, name); | 2351 *result, NULL, name); |
2337 } | 2352 } |
2338 | |
2339 return scope.CloseAndEscape(result); | 2353 return scope.CloseAndEscape(result); |
2340 } | 2354 } |
2341 | 2355 |
2342 | 2356 |
2343 void SerializedData::AllocateData(int size) { | 2357 void SerializedData::AllocateData(int size) { |
2344 DCHECK(!owns_data_); | 2358 DCHECK(!owns_data_); |
2345 data_ = NewArray<byte>(size); | 2359 data_ = NewArray<byte>(size); |
2346 size_ = size; | 2360 size_ = size; |
2347 owns_data_ = true; | 2361 owns_data_ = true; |
2348 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); | 2362 DCHECK(IsAligned(reinterpret_cast<intptr_t>(data_), kPointerAlignment)); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2560 DisallowHeapAllocation no_gc; | 2574 DisallowHeapAllocation no_gc; |
2561 SerializedCodeData* scd = new SerializedCodeData(cached_data); | 2575 SerializedCodeData* scd = new SerializedCodeData(cached_data); |
2562 SanityCheckResult r = scd->SanityCheck(isolate, source); | 2576 SanityCheckResult r = scd->SanityCheck(isolate, source); |
2563 if (r == CHECK_SUCCESS) return scd; | 2577 if (r == CHECK_SUCCESS) return scd; |
2564 cached_data->Reject(); | 2578 cached_data->Reject(); |
2565 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); | 2579 source->GetIsolate()->counters()->code_cache_reject_reason()->AddSample(r); |
2566 delete scd; | 2580 delete scd; |
2567 return NULL; | 2581 return NULL; |
2568 } | 2582 } |
2569 } } // namespace v8::internal | 2583 } } // namespace v8::internal |
OLD | NEW |