OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/code_patcher.h" | 9 #include "vm/code_patcher.h" |
10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
(...skipping 2021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2032 for (intptr_t i = 0; i < handlers.num_entries(); ++i) { | 2032 for (intptr_t i = 0; i < handlers.num_entries(); ++i) { |
2033 handlers.GetHandlerInfo(i, &info); | 2033 handlers.GetHandlerInfo(i, &info); |
2034 const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; | 2034 const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; |
2035 CodePatcher::InsertDeoptimizationCallAt(patch_pc); | 2035 CodePatcher::InsertDeoptimizationCallAt(patch_pc); |
2036 if (FLAG_trace_patching) { | 2036 if (FLAG_trace_patching) { |
2037 OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); | 2037 OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); |
2038 } | 2038 } |
2039 } | 2039 } |
2040 } | 2040 } |
2041 #else // !DBC | 2041 #else // !DBC |
2042 uword lazy_deopt_entry = | 2042 if (frame->IsMarkedForLazyDeopt()) { |
2043 StubCode::DeoptimizeLazyFromReturn_entry()->EntryPoint(); | |
2044 if (frame->pc() == lazy_deopt_entry) { | |
2045 // Deopt already scheduled. | 2043 // Deopt already scheduled. |
2046 if (FLAG_trace_deoptimization) { | 2044 if (FLAG_trace_deoptimization) { |
2047 THR_Print("Lazy deopt already scheduled for fp=%" Pp "\n", frame->fp()); | 2045 THR_Print("Lazy deopt already scheduled for fp=%" Pp "\n", frame->fp()); |
2048 } | 2046 } |
2049 } else { | 2047 } else { |
2050 uword deopt_pc = frame->pc(); | 2048 uword deopt_pc = frame->pc(); |
2051 ASSERT(optimized_code.ContainsInstructionAt(deopt_pc)); | 2049 ASSERT(optimized_code.ContainsInstructionAt(deopt_pc)); |
| 2050 |
| 2051 // N.B.: Update the pending deopt table before updating the frame. The |
| 2052 // profiler may attempt a stack walk in between. |
| 2053 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = |
| 2054 thread->isolate()->pending_deopts(); |
| 2055 for (intptr_t i = 0; i < pending_deopts->length(); i++) { |
| 2056 ASSERT((*pending_deopts)[i].fp() != frame->fp()); |
| 2057 } |
2052 PendingLazyDeopt pair(frame->fp(), deopt_pc); | 2058 PendingLazyDeopt pair(frame->fp(), deopt_pc); |
2053 thread->isolate()->pending_deopts()->Add(pair); | 2059 pending_deopts->Add(pair); |
2054 frame->set_pc(lazy_deopt_entry); | 2060 |
| 2061 #if defined(DEBUG) |
| 2062 ValidateFrames(); |
| 2063 #endif |
| 2064 |
| 2065 frame->MarkForLazyDeopt(); |
2055 | 2066 |
2056 if (FLAG_trace_deoptimization) { | 2067 if (FLAG_trace_deoptimization) { |
2057 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", | 2068 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", |
2058 frame->fp(), deopt_pc); | 2069 frame->fp(), deopt_pc); |
2059 } | 2070 } |
2060 } | 2071 } |
2061 #endif // !DBC | 2072 #endif // !DBC |
2062 | 2073 |
2063 // Mark code as dead (do not GC its embedded objects). | 2074 // Mark code as dead (do not GC its embedded objects). |
2064 optimized_code.set_is_alive(false); | 2075 optimized_code.set_is_alive(false); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 function.ToFullyQualifiedCString(), | 2164 function.ToFullyQualifiedCString(), |
2154 deoptimizing_code ? "code & frame" : "frame", | 2165 deoptimizing_code ? "code & frame" : "frame", |
2155 is_lazy_deopt ? "lazy-deopt" : ""); | 2166 is_lazy_deopt ? "lazy-deopt" : ""); |
2156 } | 2167 } |
2157 | 2168 |
2158 #if !defined(TARGET_ARCH_DBC) | 2169 #if !defined(TARGET_ARCH_DBC) |
2159 if (is_lazy_deopt) { | 2170 if (is_lazy_deopt) { |
2160 uword deopt_pc = 0; | 2171 uword deopt_pc = 0; |
2161 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = | 2172 MallocGrowableArray<PendingLazyDeopt>* pending_deopts = |
2162 isolate->pending_deopts(); | 2173 isolate->pending_deopts(); |
2163 for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) { | 2174 for (intptr_t i = 0; i < pending_deopts->length(); i++) { |
2164 if ((*pending_deopts)[i].fp() == caller_frame->fp()) { | 2175 if ((*pending_deopts)[i].fp() == caller_frame->fp()) { |
2165 deopt_pc = (*pending_deopts)[i].pc(); | 2176 deopt_pc = (*pending_deopts)[i].pc(); |
2166 break; | 2177 break; |
2167 } | 2178 } |
2168 } | 2179 } |
| 2180 #if defined(DEBUG) |
| 2181 // Check for conflicting entries. |
| 2182 for (intptr_t i = 0; i < pending_deopts->length(); i++) { |
| 2183 if ((*pending_deopts)[i].fp() == caller_frame->fp()) { |
| 2184 ASSERT((*pending_deopts)[i].pc() == deopt_pc); |
| 2185 } |
| 2186 } |
| 2187 #endif |
| 2188 if (FLAG_trace_deoptimization) { |
| 2189 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", |
| 2190 caller_frame->fp(), deopt_pc); |
| 2191 } |
| 2192 ASSERT(deopt_pc != 0); |
| 2193 |
| 2194 // N.B.: Update frame before updating pending deopt table. The profiler |
| 2195 // may attempt a stack walk in between. |
| 2196 caller_frame->set_pc(deopt_pc); |
| 2197 ASSERT(caller_frame->pc() == deopt_pc); |
| 2198 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); |
| 2199 |
2169 for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) { | 2200 for (intptr_t i = pending_deopts->length() - 1; i >= 0; i--) { |
2170 if ((*pending_deopts)[i].fp() <= caller_frame->fp()) { | 2201 if ((*pending_deopts)[i].fp() <= caller_frame->fp()) { |
2171 pending_deopts->RemoveAt(i); | 2202 pending_deopts->RemoveAt(i); |
2172 } | 2203 } |
2173 } | 2204 } |
2174 if (FLAG_trace_deoptimization) { | |
2175 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", | |
2176 caller_frame->fp(), deopt_pc); | |
2177 THR_Print("%" Pd " pending lazy deopts\n", | |
2178 pending_deopts->length()); | |
2179 } | |
2180 ASSERT(deopt_pc != 0); | |
2181 caller_frame->set_pc(deopt_pc); | |
2182 ASSERT(caller_frame->pc() == deopt_pc); | |
2183 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); | |
2184 } else { | 2205 } else { |
2185 if (FLAG_trace_deoptimization) { | 2206 if (FLAG_trace_deoptimization) { |
2186 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", | 2207 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", |
2187 caller_frame->fp(), caller_frame->pc()); | 2208 caller_frame->fp(), caller_frame->pc()); |
2188 } | 2209 } |
2189 } | 2210 } |
2190 #endif // !DBC | 2211 #endif // !DBC |
2191 | 2212 |
2192 // Copy the saved registers from the stack. | 2213 // Copy the saved registers from the stack. |
2193 fpu_register_t* fpu_registers; | 2214 fpu_register_t* fpu_registers; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2261 // Returns number of bytes to remove from the expression stack of the | 2282 // Returns number of bytes to remove from the expression stack of the |
2262 // bottom-most deoptimized frame. Those arguments were artificially injected | 2283 // bottom-most deoptimized frame. Those arguments were artificially injected |
2263 // under return address to keep them discoverable by GC that can occur during | 2284 // under return address to keep them discoverable by GC that can occur during |
2264 // materialization phase. | 2285 // materialization phase. |
2265 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { | 2286 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { |
2266 #if !defined(DART_PRECOMPILED_RUNTIME) | 2287 #if !defined(DART_PRECOMPILED_RUNTIME) |
2267 #if defined(DEBUG) | 2288 #if defined(DEBUG) |
2268 { | 2289 { |
2269 // We may rendezvous for a safepoint at entry or GC from the allocations | 2290 // We may rendezvous for a safepoint at entry or GC from the allocations |
2270 // below. Check the stack is walkable. | 2291 // below. Check the stack is walkable. |
2271 StackFrameIterator frames_iterator(StackFrameIterator::kValidateFrames); | 2292 ValidateFrames(); |
2272 StackFrame* frame = frames_iterator.NextFrame(); | |
2273 while (frame != NULL) { | |
2274 frame = frames_iterator.NextFrame(); | |
2275 } | |
2276 } | 2293 } |
2277 #endif | 2294 #endif |
2278 DeoptContext* deopt_context = isolate->deopt_context(); | 2295 DeoptContext* deopt_context = isolate->deopt_context(); |
2279 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); | 2296 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); |
2280 isolate->set_deopt_context(NULL); | 2297 isolate->set_deopt_context(NULL); |
2281 delete deopt_context; | 2298 delete deopt_context; |
2282 | 2299 |
2283 // Return value tells deoptimization stub to remove the given number of bytes | 2300 // Return value tells deoptimization stub to remove the given number of bytes |
2284 // from the stack. | 2301 // from the stack. |
2285 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); | 2302 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2356 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2373 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
2357 const TypedData& new_data = | 2374 const TypedData& new_data = |
2358 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2375 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
2359 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2376 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
2360 typed_data_cell.SetAt(0, new_data); | 2377 typed_data_cell.SetAt(0, new_data); |
2361 arguments.SetReturn(new_data); | 2378 arguments.SetReturn(new_data); |
2362 } | 2379 } |
2363 | 2380 |
2364 | 2381 |
2365 } // namespace dart | 2382 } // namespace dart |
OLD | NEW |