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