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