OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <sstream> | 9 #include <sstream> |
10 | 10 |
(...skipping 10119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10130 Isolate* isolate = shared->GetIsolate(); | 10130 Isolate* isolate = shared->GetIsolate(); |
10131 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 10131 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
10132 Handle<Object> value(shared->optimized_code_map(), isolate); | 10132 Handle<Object> value(shared->optimized_code_map(), isolate); |
10133 if (value->IsSmi()) return; // Empty code maps are unsupported. | 10133 if (value->IsSmi()) return; // Empty code maps are unsupported. |
10134 Handle<FixedArray> code_map = Handle<FixedArray>::cast(value); | 10134 Handle<FixedArray> code_map = Handle<FixedArray>::cast(value); |
10135 code_map->set(kSharedCodeIndex, *code); | 10135 code_map->set(kSharedCodeIndex, *code); |
10136 } | 10136 } |
10137 | 10137 |
10138 | 10138 |
10139 void SharedFunctionInfo::AddToOptimizedCodeMap( | 10139 void SharedFunctionInfo::AddToOptimizedCodeMap( |
10140 Handle<SharedFunctionInfo> shared, | 10140 Handle<SharedFunctionInfo> shared, Handle<Context> native_context, |
10141 Handle<Context> native_context, | 10141 Handle<HeapObject> code, Handle<FixedArray> literals, |
10142 Handle<Code> code, | |
10143 Handle<FixedArray> literals, | |
10144 BailoutId osr_ast_id) { | 10142 BailoutId osr_ast_id) { |
10145 Isolate* isolate = shared->GetIsolate(); | 10143 Isolate* isolate = shared->GetIsolate(); |
10146 DCHECK(!shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code); | 10144 DCHECK(*code == isolate->heap()->undefined_value() || |
10147 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); | 10145 !shared->SearchOptimizedCodeMap(*native_context, osr_ast_id).code); |
| 10146 DCHECK(*code == isolate->heap()->undefined_value() || |
| 10147 Code::cast(*code)->kind() == Code::OPTIMIZED_FUNCTION); |
10148 DCHECK(native_context->IsNativeContext()); | 10148 DCHECK(native_context->IsNativeContext()); |
10149 STATIC_ASSERT(kEntryLength == 4); | 10149 STATIC_ASSERT(kEntryLength == 4); |
10150 Handle<FixedArray> new_code_map; | 10150 Handle<FixedArray> new_code_map; |
10151 Handle<Object> value(shared->optimized_code_map(), isolate); | 10151 Handle<Object> value(shared->optimized_code_map(), isolate); |
10152 int old_length; | 10152 int entry; |
10153 if (value->IsSmi()) { | 10153 if (value->IsSmi()) { |
10154 // No optimized code map. | 10154 // No optimized code map. |
10155 DCHECK_EQ(0, Smi::cast(*value)->value()); | 10155 DCHECK_EQ(0, Smi::cast(*value)->value()); |
10156 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); | 10156 new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED); |
10157 old_length = kEntriesStart; | 10157 entry = kEntriesStart; |
10158 } else { | 10158 } else { |
| 10159 Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value); |
| 10160 entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id); |
| 10161 if (entry > kSharedCodeIndex) { |
| 10162 // Found an existing context-specific entry, it must not contain any code. |
| 10163 DCHECK_EQ(isolate->heap()->undefined_value(), |
| 10164 old_code_map->get(entry + kCachedCodeOffset)); |
| 10165 // Just set the code and literals to the entry. |
| 10166 old_code_map->set(entry + kCachedCodeOffset, *code); |
| 10167 old_code_map->set(entry + kLiteralsOffset, *literals); |
| 10168 return; |
| 10169 } |
| 10170 |
10159 // Copy old optimized code map and append one new entry. | 10171 // Copy old optimized code map and append one new entry. |
10160 Handle<FixedArray> old_code_map = Handle<FixedArray>::cast(value); | |
10161 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( | 10172 new_code_map = isolate->factory()->CopyFixedArrayAndGrow( |
10162 old_code_map, kEntryLength, TENURED); | 10173 old_code_map, kEntryLength, TENURED); |
10163 old_length = old_code_map->length(); | 10174 int old_length = old_code_map->length(); |
10164 // Zap the old map to avoid any stale entries. Note that this is required | 10175 // Zap the old map to avoid any stale entries. Note that this is required |
10165 // for correctness because entries are being treated weakly by the GC. | 10176 // for correctness because entries are being treated weakly by the GC. |
10166 MemsetPointer(old_code_map->data_start(), isolate->heap()->the_hole_value(), | 10177 MemsetPointer(old_code_map->data_start(), isolate->heap()->the_hole_value(), |
10167 old_length); | 10178 old_length); |
| 10179 entry = old_length; |
10168 } | 10180 } |
10169 new_code_map->set(old_length + kContextOffset, *native_context); | 10181 new_code_map->set(entry + kContextOffset, *native_context); |
10170 new_code_map->set(old_length + kCachedCodeOffset, *code); | 10182 new_code_map->set(entry + kCachedCodeOffset, *code); |
10171 new_code_map->set(old_length + kLiteralsOffset, *literals); | 10183 new_code_map->set(entry + kLiteralsOffset, *literals); |
10172 new_code_map->set(old_length + kOsrAstIdOffset, | 10184 new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt())); |
10173 Smi::FromInt(osr_ast_id.ToInt())); | |
10174 | 10185 |
10175 #ifdef DEBUG | 10186 #ifdef DEBUG |
10176 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { | 10187 for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) { |
10177 DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext()); | 10188 DCHECK(new_code_map->get(i + kContextOffset)->IsNativeContext()); |
10178 DCHECK(new_code_map->get(i + kCachedCodeOffset)->IsCode()); | 10189 Object* code = new_code_map->get(i + kCachedCodeOffset); |
10179 DCHECK(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() == | 10190 if (code != isolate->heap()->undefined_value()) { |
10180 Code::OPTIMIZED_FUNCTION); | 10191 DCHECK(code->IsCode()); |
| 10192 DCHECK(Code::cast(code)->kind() == Code::OPTIMIZED_FUNCTION); |
| 10193 } |
10181 DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray()); | 10194 DCHECK(new_code_map->get(i + kLiteralsOffset)->IsFixedArray()); |
10182 DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); | 10195 DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi()); |
10183 } | 10196 } |
10184 #endif | 10197 #endif |
10185 shared->set_optimized_code_map(*new_code_map); | 10198 shared->set_optimized_code_map(*new_code_map); |
10186 } | 10199 } |
10187 | 10200 |
10188 | 10201 |
10189 void SharedFunctionInfo::ClearOptimizedCodeMap() { | 10202 void SharedFunctionInfo::ClearOptimizedCodeMap() { |
10190 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 10203 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
10191 | 10204 |
10192 // If the next map link slot is already used then the function was | 10205 // If the next map link slot is already used then the function was |
10193 // enqueued with code flushing and we remove it now. | 10206 // enqueued with code flushing and we remove it now. |
10194 if (!code_map->get(kNextMapIndex)->IsUndefined()) { | 10207 if (!code_map->get(kNextMapIndex)->IsUndefined()) { |
10195 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); | 10208 CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher(); |
10196 flusher->EvictOptimizedCodeMap(this); | 10209 flusher->EvictOptimizedCodeMap(this); |
10197 } | 10210 } |
10198 | 10211 |
10199 DCHECK(code_map->get(kNextMapIndex)->IsUndefined()); | 10212 DCHECK(code_map->get(kNextMapIndex)->IsUndefined()); |
10200 set_optimized_code_map(Smi::FromInt(0)); | 10213 set_optimized_code_map(Smi::FromInt(0)); |
10201 } | 10214 } |
10202 | 10215 |
10203 | 10216 |
10204 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 10217 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
10205 const char* reason) { | 10218 const char* reason) { |
10206 DisallowHeapAllocation no_gc; | 10219 DisallowHeapAllocation no_gc; |
10207 if (optimized_code_map()->IsSmi()) return; | 10220 if (optimized_code_map()->IsSmi()) return; |
10208 | 10221 |
| 10222 Heap* heap = GetHeap(); |
10209 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 10223 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
10210 int dst = kEntriesStart; | 10224 int dst = kEntriesStart; |
10211 int length = code_map->length(); | 10225 int length = code_map->length(); |
10212 for (int src = kEntriesStart; src < length; src += kEntryLength) { | 10226 for (int src = kEntriesStart; src < length; src += kEntryLength) { |
10213 DCHECK(code_map->get(src)->IsNativeContext()); | 10227 DCHECK(code_map->get(src)->IsNativeContext()); |
10214 if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) { | 10228 if (code_map->get(src + kCachedCodeOffset) == optimized_code) { |
10215 // Evict the src entry by not copying it to the dst entry. | 10229 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); |
10216 if (FLAG_trace_opt) { | 10230 if (FLAG_trace_opt) { |
10217 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 10231 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
10218 ShortPrint(); | 10232 ShortPrint(); |
10219 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); | |
10220 if (osr.IsNone()) { | 10233 if (osr.IsNone()) { |
10221 PrintF("]\n"); | 10234 PrintF("]\n"); |
10222 } else { | 10235 } else { |
10223 PrintF(" (osr ast id %d)]\n", osr.ToInt()); | 10236 PrintF(" (osr ast id %d)]\n", osr.ToInt()); |
10224 } | 10237 } |
10225 } | 10238 } |
10226 } else { | 10239 if (!osr.IsNone()) { |
10227 // Keep the src entry by copying it to the dst entry. | 10240 // Evict the src entry by not copying it to the dst entry. |
10228 if (dst != src) { | 10241 continue; |
10229 code_map->set(dst + kContextOffset, | |
10230 code_map->get(src + kContextOffset)); | |
10231 code_map->set(dst + kCachedCodeOffset, | |
10232 code_map->get(src + kCachedCodeOffset)); | |
10233 code_map->set(dst + kLiteralsOffset, | |
10234 code_map->get(src + kLiteralsOffset)); | |
10235 code_map->set(dst + kOsrAstIdOffset, | |
10236 code_map->get(src + kOsrAstIdOffset)); | |
10237 } | 10242 } |
10238 dst += kEntryLength; | 10243 // In case of non-OSR entry just clear the code in order to proceed |
| 10244 // sharing literals. |
| 10245 code_map->set_undefined(src + kCachedCodeOffset); |
10239 } | 10246 } |
| 10247 |
| 10248 // Keep the src entry by copying it to the dst entry. |
| 10249 if (dst != src) { |
| 10250 code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset)); |
| 10251 code_map->set(dst + kCachedCodeOffset, |
| 10252 code_map->get(src + kCachedCodeOffset)); |
| 10253 code_map->set(dst + kLiteralsOffset, |
| 10254 code_map->get(src + kLiteralsOffset)); |
| 10255 code_map->set(dst + kOsrAstIdOffset, |
| 10256 code_map->get(src + kOsrAstIdOffset)); |
| 10257 } |
| 10258 dst += kEntryLength; |
10240 } | 10259 } |
10241 if (code_map->get(kSharedCodeIndex) == optimized_code) { | 10260 if (code_map->get(kSharedCodeIndex) == optimized_code) { |
10242 // Evict context-independent code as well. | 10261 // Evict context-independent code as well. |
10243 code_map->set_undefined(kSharedCodeIndex); | 10262 code_map->set_undefined(kSharedCodeIndex); |
10244 if (FLAG_trace_opt) { | 10263 if (FLAG_trace_opt) { |
10245 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 10264 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
10246 ShortPrint(); | 10265 ShortPrint(); |
10247 PrintF(" (context-independent code)]\n"); | 10266 PrintF(" (context-independent code)]\n"); |
10248 } | 10267 } |
10249 } | 10268 } |
10250 if (dst != length) { | 10269 if (dst != length) { |
10251 // Always trim even when array is cleared because of heap verifier. | 10270 // Always trim even when array is cleared because of heap verifier. |
10252 GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map, | 10271 heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map, |
10253 length - dst); | 10272 length - dst); |
10254 if (code_map->length() == kEntriesStart && | 10273 if (code_map->length() == kEntriesStart && |
10255 code_map->get(kSharedCodeIndex)->IsUndefined()) { | 10274 code_map->get(kSharedCodeIndex)->IsUndefined()) { |
10256 ClearOptimizedCodeMap(); | 10275 ClearOptimizedCodeMap(); |
10257 } | 10276 } |
10258 } | 10277 } |
10259 } | 10278 } |
10260 | 10279 |
10261 | 10280 |
10262 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 10281 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { |
10263 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 10282 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
(...skipping 994 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11258 opt_count() >= FLAG_max_opt_count) { | 11277 opt_count() >= FLAG_max_opt_count) { |
11259 // Re-enable optimizations if they were disabled due to opt_count limit. | 11278 // Re-enable optimizations if they were disabled due to opt_count limit. |
11260 set_optimization_disabled(false); | 11279 set_optimization_disabled(false); |
11261 } | 11280 } |
11262 set_opt_count(0); | 11281 set_opt_count(0); |
11263 set_deopt_count(0); | 11282 set_deopt_count(0); |
11264 } | 11283 } |
11265 } | 11284 } |
11266 | 11285 |
11267 | 11286 |
11268 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( | 11287 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context, |
11269 Context* native_context, BailoutId osr_ast_id) { | 11288 BailoutId osr_ast_id) { |
11270 DisallowHeapAllocation no_gc; | 11289 DisallowHeapAllocation no_gc; |
11271 DCHECK(native_context->IsNativeContext()); | 11290 DCHECK(native_context->IsNativeContext()); |
11272 Object* value = optimized_code_map(); | 11291 Object* value = optimized_code_map(); |
11273 if (!value->IsSmi()) { | 11292 if (!value->IsSmi()) { |
11274 FixedArray* optimized_code_map = FixedArray::cast(value); | 11293 FixedArray* optimized_code_map = FixedArray::cast(value); |
11275 int length = optimized_code_map->length(); | 11294 int length = optimized_code_map->length(); |
11276 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); | 11295 Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt()); |
11277 for (int i = kEntriesStart; i < length; i += kEntryLength) { | 11296 for (int i = kEntriesStart; i < length; i += kEntryLength) { |
11278 if (optimized_code_map->get(i + kContextOffset) == native_context && | 11297 if (optimized_code_map->get(i + kContextOffset) == native_context && |
11279 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { | 11298 optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) { |
11280 return {Code::cast(optimized_code_map->get(i + kCachedCodeOffset)), | 11299 return i; |
11281 FixedArray::cast(optimized_code_map->get(i + kLiteralsOffset))}; | |
11282 } | 11300 } |
11283 } | 11301 } |
11284 Object* shared_code = optimized_code_map->get(kSharedCodeIndex); | 11302 Object* shared_code = optimized_code_map->get(kSharedCodeIndex); |
11285 if (shared_code->IsCode() && osr_ast_id.IsNone()) { | 11303 if (shared_code->IsCode() && osr_ast_id.IsNone()) { |
11286 return {Code::cast(shared_code), nullptr}; | 11304 return kSharedCodeIndex; |
11287 } | |
11288 if (FLAG_trace_opt) { | |
11289 PrintF("[didn't find optimized code in optimized code map for "); | |
11290 ShortPrint(); | |
11291 PrintF("]\n"); | |
11292 } | 11305 } |
11293 } | 11306 } |
11294 return {nullptr, nullptr}; | 11307 return -1; |
11295 } | 11308 } |
11296 | 11309 |
11297 | 11310 |
| 11311 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap( |
| 11312 Context* native_context, BailoutId osr_ast_id) { |
| 11313 CodeAndLiterals result = {nullptr, nullptr}; |
| 11314 int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id); |
| 11315 if (entry != kNotFound) { |
| 11316 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 11317 if (entry == kSharedCodeIndex) { |
| 11318 result = {Code::cast(code_map->get(kSharedCodeIndex)), nullptr}; |
| 11319 |
| 11320 } else { |
| 11321 DCHECK_LE(entry + kEntryLength, code_map->length()); |
| 11322 Object* code = code_map->get(entry + kCachedCodeOffset); |
| 11323 result = {code->IsUndefined() ? nullptr : Code::cast(code), |
| 11324 FixedArray::cast(code_map->get(entry + kLiteralsOffset))}; |
| 11325 } |
| 11326 } |
| 11327 if (FLAG_trace_opt && !optimized_code_map()->IsSmi() && |
| 11328 result.code == nullptr) { |
| 11329 PrintF("[didn't find optimized code in optimized code map for "); |
| 11330 ShortPrint(); |
| 11331 PrintF("]\n"); |
| 11332 } |
| 11333 return result; |
| 11334 } |
| 11335 |
| 11336 |
11298 #define DECLARE_TAG(ignore1, name, ignore2) name, | 11337 #define DECLARE_TAG(ignore1, name, ignore2) name, |
11299 const char* const VisitorSynchronization::kTags[ | 11338 const char* const VisitorSynchronization::kTags[ |
11300 VisitorSynchronization::kNumberOfSyncTags] = { | 11339 VisitorSynchronization::kNumberOfSyncTags] = { |
11301 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) | 11340 VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG) |
11302 }; | 11341 }; |
11303 #undef DECLARE_TAG | 11342 #undef DECLARE_TAG |
11304 | 11343 |
11305 | 11344 |
11306 #define DECLARE_TAG(ignore1, ignore2, name) name, | 11345 #define DECLARE_TAG(ignore1, ignore2, name) name, |
11307 const char* const VisitorSynchronization::kTagNames[ | 11346 const char* const VisitorSynchronization::kTagNames[ |
(...skipping 5382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16690 if (cell->value() != *new_value) { | 16729 if (cell->value() != *new_value) { |
16691 cell->set_value(*new_value); | 16730 cell->set_value(*new_value); |
16692 Isolate* isolate = cell->GetIsolate(); | 16731 Isolate* isolate = cell->GetIsolate(); |
16693 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16732 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16694 isolate, DependentCode::kPropertyCellChangedGroup); | 16733 isolate, DependentCode::kPropertyCellChangedGroup); |
16695 } | 16734 } |
16696 } | 16735 } |
16697 | 16736 |
16698 } // namespace internal | 16737 } // namespace internal |
16699 } // namespace v8 | 16738 } // namespace v8 |
OLD | NEW |