| 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 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1928 Exceptions::PropagateError(error); | 1928 Exceptions::PropagateError(error); |
| 1929 } | 1929 } |
| 1930 const Code& unoptimized_code = | 1930 const Code& unoptimized_code = |
| 1931 Code::Handle(zone, function.unoptimized_code()); | 1931 Code::Handle(zone, function.unoptimized_code()); |
| 1932 ASSERT(!unoptimized_code.IsNull()); | 1932 ASSERT(!unoptimized_code.IsNull()); |
| 1933 // The switch to unoptimized code may have already occurred. | 1933 // The switch to unoptimized code may have already occurred. |
| 1934 if (function.HasOptimizedCode()) { | 1934 if (function.HasOptimizedCode()) { |
| 1935 function.SwitchToUnoptimizedCode(); | 1935 function.SwitchToUnoptimizedCode(); |
| 1936 } | 1936 } |
| 1937 | 1937 |
| 1938 #if defined(TARGET_ARCH_DBC) | |
| 1939 const Instructions& instrs = | |
| 1940 Instructions::Handle(zone, optimized_code.instructions()); | |
| 1941 { | |
| 1942 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); | |
| 1943 CodePatcher::InsertDeoptimizationCallAt(frame->pc()); | |
| 1944 if (FLAG_trace_patching) { | |
| 1945 const String& name = String::Handle(function.name()); | |
| 1946 OS::PrintErr("InsertDeoptimizationCallAt: 0x%" Px " for %s\n", | |
| 1947 frame->pc(), name.ToCString()); | |
| 1948 } | |
| 1949 const ExceptionHandlers& handlers = | |
| 1950 ExceptionHandlers::Handle(zone, optimized_code.exception_handlers()); | |
| 1951 ExceptionHandlerInfo info; | |
| 1952 for (intptr_t i = 0; i < handlers.num_entries(); ++i) { | |
| 1953 handlers.GetHandlerInfo(i, &info); | |
| 1954 const uword patch_pc = instrs.PayloadStart() + info.handler_pc_offset; | |
| 1955 CodePatcher::InsertDeoptimizationCallAt(patch_pc); | |
| 1956 if (FLAG_trace_patching) { | |
| 1957 OS::PrintErr(" at handler 0x%" Px "\n", patch_pc); | |
| 1958 } | |
| 1959 } | |
| 1960 } | |
| 1961 #else // !DBC | |
| 1962 if (frame->IsMarkedForLazyDeopt()) { | 1938 if (frame->IsMarkedForLazyDeopt()) { |
| 1963 // Deopt already scheduled. | 1939 // Deopt already scheduled. |
| 1964 if (FLAG_trace_deoptimization) { | 1940 if (FLAG_trace_deoptimization) { |
| 1965 THR_Print("Lazy deopt already scheduled for fp=%" Pp "\n", frame->fp()); | 1941 THR_Print("Lazy deopt already scheduled for fp=%" Pp "\n", frame->fp()); |
| 1966 } | 1942 } |
| 1967 } else { | 1943 } else { |
| 1968 uword deopt_pc = frame->pc(); | 1944 uword deopt_pc = frame->pc(); |
| 1969 ASSERT(optimized_code.ContainsInstructionAt(deopt_pc)); | 1945 ASSERT(optimized_code.ContainsInstructionAt(deopt_pc)); |
| 1970 | 1946 |
| 1971 #if defined(DEBUG) | 1947 #if defined(DEBUG) |
| 1972 ValidateFrames(); | 1948 ValidateFrames(); |
| 1973 #endif | 1949 #endif |
| 1974 | 1950 |
| 1975 // N.B.: Update the pending deopt table before updating the frame. The | 1951 // N.B.: Update the pending deopt table before updating the frame. The |
| 1976 // profiler may attempt a stack walk in between. | 1952 // profiler may attempt a stack walk in between. |
| 1977 thread->isolate()->AddPendingDeopt(frame->fp(), deopt_pc); | 1953 thread->isolate()->AddPendingDeopt(frame->fp(), deopt_pc); |
| 1978 frame->MarkForLazyDeopt(); | 1954 frame->MarkForLazyDeopt(); |
| 1979 | 1955 |
| 1980 if (FLAG_trace_deoptimization) { | 1956 if (FLAG_trace_deoptimization) { |
| 1981 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", | 1957 THR_Print("Lazy deopt scheduled for fp=%" Pp ", pc=%" Pp "\n", |
| 1982 frame->fp(), deopt_pc); | 1958 frame->fp(), deopt_pc); |
| 1983 } | 1959 } |
| 1984 } | 1960 } |
| 1985 #endif // !DBC | |
| 1986 | 1961 |
| 1987 // Mark code as dead (do not GC its embedded objects). | 1962 // Mark code as dead (do not GC its embedded objects). |
| 1988 optimized_code.set_is_alive(false); | 1963 optimized_code.set_is_alive(false); |
| 1989 } | 1964 } |
| 1990 | 1965 |
| 1991 | 1966 |
| 1992 // Currently checks only that all optimized frames have kDeoptIndex | 1967 // Currently checks only that all optimized frames have kDeoptIndex |
| 1993 // and unoptimized code has the kDeoptAfter. | 1968 // and unoptimized code has the kDeoptAfter. |
| 1994 void DeoptimizeFunctionsOnStack() { | 1969 void DeoptimizeFunctionsOnStack() { |
| 1995 DartFrameIterator iterator; | 1970 DartFrameIterator iterator; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2073 Function::Handle(thread->zone(), optimized_code.function()); | 2048 Function::Handle(thread->zone(), optimized_code.function()); |
| 2074 const bool deoptimizing_code = top_function.HasOptimizedCode(); | 2049 const bool deoptimizing_code = top_function.HasOptimizedCode(); |
| 2075 if (FLAG_trace_deoptimization) { | 2050 if (FLAG_trace_deoptimization) { |
| 2076 const Function& function = Function::Handle(optimized_code.function()); | 2051 const Function& function = Function::Handle(optimized_code.function()); |
| 2077 THR_Print("== Deoptimizing code for '%s', %s, %s\n", | 2052 THR_Print("== Deoptimizing code for '%s', %s, %s\n", |
| 2078 function.ToFullyQualifiedCString(), | 2053 function.ToFullyQualifiedCString(), |
| 2079 deoptimizing_code ? "code & frame" : "frame", | 2054 deoptimizing_code ? "code & frame" : "frame", |
| 2080 is_lazy_deopt ? "lazy-deopt" : ""); | 2055 is_lazy_deopt ? "lazy-deopt" : ""); |
| 2081 } | 2056 } |
| 2082 | 2057 |
| 2083 #if !defined(TARGET_ARCH_DBC) | |
| 2084 if (is_lazy_deopt) { | 2058 if (is_lazy_deopt) { |
| 2085 uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp()); | 2059 uword deopt_pc = isolate->FindPendingDeopt(caller_frame->fp()); |
| 2086 if (FLAG_trace_deoptimization) { | 2060 if (FLAG_trace_deoptimization) { |
| 2087 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(), | 2061 THR_Print("Lazy deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(), |
| 2088 deopt_pc); | 2062 deopt_pc); |
| 2089 } | 2063 } |
| 2090 | 2064 |
| 2091 // N.B.: Update frame before updating pending deopt table. The profiler | 2065 // N.B.: Update frame before updating pending deopt table. The profiler |
| 2092 // may attempt a stack walk in between. | 2066 // may attempt a stack walk in between. |
| 2093 caller_frame->set_pc(deopt_pc); | 2067 caller_frame->set_pc(deopt_pc); |
| 2068 ASSERT(!caller_frame->IsMarkedForLazyDeopt()); |
| 2094 ASSERT(caller_frame->pc() == deopt_pc); | 2069 ASSERT(caller_frame->pc() == deopt_pc); |
| 2095 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); | 2070 ASSERT(optimized_code.ContainsInstructionAt(caller_frame->pc())); |
| 2096 isolate->ClearPendingDeoptsAtOrBelow(caller_frame->fp()); | 2071 isolate->ClearPendingDeoptsAtOrBelow(caller_frame->fp()); |
| 2097 } else { | 2072 } else { |
| 2098 if (FLAG_trace_deoptimization) { | 2073 if (FLAG_trace_deoptimization) { |
| 2099 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(), | 2074 THR_Print("Eager deopt fp=%" Pp " pc=%" Pp "\n", caller_frame->fp(), |
| 2100 caller_frame->pc()); | 2075 caller_frame->pc()); |
| 2101 } | 2076 } |
| 2102 } | 2077 } |
| 2103 #endif // !DBC | |
| 2104 | 2078 |
| 2105 // Copy the saved registers from the stack. | 2079 // Copy the saved registers from the stack. |
| 2106 fpu_register_t* fpu_registers; | 2080 fpu_register_t* fpu_registers; |
| 2107 intptr_t* cpu_registers; | 2081 intptr_t* cpu_registers; |
| 2108 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); | 2082 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); |
| 2109 | 2083 |
| 2110 // Create the DeoptContext. | 2084 // Create the DeoptContext. |
| 2111 DeoptContext* deopt_context = new DeoptContext( | 2085 DeoptContext* deopt_context = new DeoptContext( |
| 2112 caller_frame, optimized_code, DeoptContext::kDestIsOriginalFrame, | 2086 caller_frame, optimized_code, DeoptContext::kDestIsOriginalFrame, |
| 2113 fpu_registers, cpu_registers, is_lazy_deopt != 0, deoptimizing_code); | 2087 fpu_registers, cpu_registers, is_lazy_deopt != 0, deoptimizing_code); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 2235 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
| 2262 const TypedData& new_data = | 2236 const TypedData& new_data = |
| 2263 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 2237 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
| 2264 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 2238 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
| 2265 typed_data_cell.SetAt(0, new_data); | 2239 typed_data_cell.SetAt(0, new_data); |
| 2266 arguments.SetReturn(new_data); | 2240 arguments.SetReturn(new_data); |
| 2267 } | 2241 } |
| 2268 | 2242 |
| 2269 | 2243 |
| 2270 } // namespace dart | 2244 } // namespace dart |
| OLD | NEW |