Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(531)

Unified Diff: runtime/vm/code_generator.cc

Issue 10836020: First step toward deoptimization using deoptimization info: splits deoptimization into two steps: c… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/isolate.h » ('j') | runtime/vm/isolate.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
===================================================================
--- runtime/vm/code_generator.cc (revision 10031)
+++ runtime/vm/code_generator.cc (working copy)
@@ -12,6 +12,7 @@
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/exceptions.h"
+#include "vm/intermediate_language.h"
#include "vm/object_store.h"
#include "vm/message.h"
#include "vm/message_handler.h"
@@ -1404,87 +1405,140 @@
}
-// The top Dart frame belongs to the optimized method that needs to be
-// deoptimized. The pc of the Dart frame points to the deoptimization point.
-// Find the node id of the deoptimization point and find the continuation
-// pc in the unoptimized code.
-// Since both unoptimized and optimized code have the same layout, we need only
-// to patch the pc of the Dart frame and to disable/enable appropriate code.
-DEFINE_RUNTIME_ENTRY(Deoptimize, 1) {
- ASSERT(arguments.Count() == kDeoptimizeRuntimeEntry.argument_count());
- const Smi& deoptimization_reason_id = Smi::CheckedHandle(arguments.At(0));
- DartFrameIterator iterator;
+static intptr_t GetDeoptInfo(const Code& code, uword pc) {
+ const PcDescriptors& descriptors =
+ PcDescriptors::Handle(code.pc_descriptors());
+ ASSERT(!descriptors.IsNull());
+ // Locate deopt id at deoptimization point inside optimized code.
+ for (int i = 0; i < descriptors.Length(); i++) {
+ if (static_cast<uword>(descriptors.PC(i)) == pc) {
+ return descriptors.NodeId(i);
+ }
+ }
+ return Computation::kNoCid;
+}
+
+
+// Copy saved registers and caller's frame into temporary buffers.
+// Access the deopt information for the deoptimziation point.
siva 2012/07/31 01:59:12 deoptimization
srdjan 2012/07/31 16:21:28 Done.
+// Return the new stack size (including PC marker and deopt return address,
+// excluding FP).
+DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
+ intptr_t deopt_reason,
+ intptr_t* saved_registers_address) {
+ Isolate* isolate = Isolate::Current();
+ Zone zone(isolate);
+ HANDLESCOPE(isolate);
+
+ // Copy saved registers.
+ intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters];
siva 2012/07/31 01:59:12 ASSERT(saved_registers_address != NULL); ASSERT(re
srdjan 2012/07/31 16:21:28 Done.
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+ registers_copy[i] = *saved_registers_address;
+ saved_registers_address++;
+ }
+ isolate->set_deopt_registers_copy(registers_copy);
+
+ DartFrameIterator iterator(reinterpret_cast<uword>(saved_registers_address));
siva 2012/07/31 01:59:12 maybe instead of saved_registers_address you could
srdjan 2012/07/31 16:21:28 Done.
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
+ ASSERT(optimized_code.is_optimized());
+
+ const intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc());
+ ASSERT(deopt_id != Computation::kNoCid);
+
+ // Add incoming arguments.
const Function& function = Function::Handle(optimized_code.function());
+ // Think of copied arguments.
+ const intptr_t num_args = (function.num_optional_parameters() > 0) ?
+ 0 : function.num_fixed_parameters();
+ // FP, PC marker and return address will all be copied.
+ const intptr_t frame_copy_size =
+ 1 // Deoptimized function's return address: caller_frame->pc().
+ + ((caller_frame->fp() - caller_frame->sp()) / kWordSize)
+ + 1 // PC marker.
+ + 1 // Caller return address.
+ + num_args;
+ intptr_t* frame_copy = new intptr_t[frame_copy_size];
+ isolate->SetDeoptFrameCopy(frame_copy, frame_copy_size);
siva 2012/07/31 01:59:12 for consistency you should probably set frame_copy
srdjan 2012/07/31 16:21:28 Done.
+ // Include the return address of deoptimized code.
+ intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
+ for (intptr_t i = 0; i < frame_copy_size; i++) {
+ frame_copy[i] = *(start + i);
+ }
+ if (FLAG_trace_deopt) {
+ OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s'\n",
+ deopt_reason,
+ DeoptReasonToText(deopt_reason),
+ caller_frame->pc(),
+ deopt_id,
+ function.ToFullyQualifiedCString());
+ }
+ // TODO(srdjan): find deopt info and the size of stack, currently stack size
+ // is the same as before.
+ const intptr_t stack_size_in_bytes = caller_frame->fp() - caller_frame->sp();
+ // Include the space for return address.
+ return stack_size_in_bytes + kWordSize;
+}
+END_LEAF_RUNTIME_ENTRY
+
+
+// The stack has been adjusted to fit all values for unoptimized frame.
+// Fill the unoptimized frame.
+DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) {
+ Isolate* isolate = Isolate::Current();
+ Zone zone(isolate);
+ HANDLESCOPE(isolate);
+
+ DartFrameIterator iterator(last_fp);
+ StackFrame* caller_frame = iterator.NextFrame();
+ ASSERT(caller_frame != NULL);
+ const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
+ const Function& function = Function::Handle(optimized_code.function());
ASSERT(!function.IsNull());
const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
siva 2012/07/31 01:59:12 At this point it is possible that there is no unop
srdjan 2012/07/31 16:21:28 Function always refers to unoptimized code, i.e.,
ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
- const PcDescriptors& descriptors =
- PcDescriptors::Handle(optimized_code.pc_descriptors());
- ASSERT(!descriptors.IsNull());
- // Locate node id at deoptimization point inside optimized code.
- intptr_t deopt_node_id = AstNode::kNoId;
- intptr_t deopt_token_index = 0;
- for (int i = 0; i < descriptors.Length(); i++) {
- if (static_cast<uword>(descriptors.PC(i)) == caller_frame->pc()) {
- deopt_node_id = descriptors.NodeId(i);
- deopt_token_index = descriptors.TokenIndex(i);
- break;
- }
- }
- ASSERT(deopt_node_id != AstNode::kNoId);
- uword continue_at_pc =
- unoptimized_code.GetDeoptPcAtNodeId(deopt_node_id);
- ASSERT(continue_at_pc != 0);
+
+ intptr_t* frame_copy = isolate->deopt_frame_copy();
siva 2012/07/31 01:59:12 the setter function is named SetDeoptFrameCopy and
srdjan 2012/07/31 16:21:28 SetDeoptFrameCopy sets the size and the buffer, it
+ intptr_t* registers_copy = isolate->deopt_registers_copy();
siva 2012/07/31 01:59:12 Where is registers_copy used in this code?
srdjan 2012/07/31 16:21:28 Current deoptimization stubs already save the regi
+
+ intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc());
+ ASSERT(deopt_id != Computation::kNoCid);
+ uword continue_at_pc = unoptimized_code.GetDeoptPcAtNodeId(deopt_id);
if (FLAG_trace_deopt) {
- OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s' "
- "-> continue at 0x%x \n",
- deoptimization_reason_id.Value(),
- DeoptReasonToText(deoptimization_reason_id.Value()),
- caller_frame->pc(),
- deopt_node_id,
- function.ToFullyQualifiedCString(),
- continue_at_pc);
- const Class& cls = Class::Handle(function.owner());
- const Script& script = Script::Handle(cls.script());
- intptr_t line, column;
- script.GetTokenLocation(deopt_token_index, &line, &column);
- OS::Print(" Line: %d Column: %d ", line, column);
- OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString());
+ OS::Print(" -> continue at 0x%x\n", continue_at_pc);
+ // TODO(srdjan): If we could allow GC, we could print the line where
+ // deoptimization occured.
}
+ const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size();
+ // TODO(srdjan): Use deopt info to copy the values to right place.
+ const intptr_t pc_marker_index =
+ ((caller_frame->fp() - caller_frame->sp()) / kWordSize);
// Patch the return PC and saved PC marker in frame to point to the
// unoptimized version.
- caller_frame->set_pc(continue_at_pc);
- caller_frame->SetEntrypointMarker(
- unoptimized_code.EntryPoint() +
- AssemblerMacros::kOffsetOfSavedPCfromEntrypoint);
+ frame_copy[0] = continue_at_pc;
+ frame_copy[pc_marker_index] = unoptimized_code.EntryPoint() +
+ AssemblerMacros::kOffsetOfSavedPCfromEntrypoint;
+ intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
+ for (intptr_t i = 0; i < deopt_frame_copy_size; i++) {
+ *(start + i) = frame_copy[i];
+ }
+ isolate->SetDeoptFrameCopy(NULL, 0);
+ isolate->set_deopt_registers_copy(NULL);
+ delete[] frame_copy;
+ delete[] registers_copy;
// Clear invocation counter so that the function gets optimized after
- // types/classes have been collected.
+ // classes have been collected.
function.set_usage_counter(0);
function.set_deoptimization_counter(function.deoptimization_counter() + 1);
- // We have to skip the following otherwise the compiler will complain
- // when it attempts to install unoptimized code into a function that
- // was already deoptimized.
if (function.HasOptimizedCode()) {
- // Get unoptimized code. Compilation restores (reenables) the entry of
- // unoptimized code.
- const Error& error = Error::Handle(Compiler::CompileFunction(function));
- if (!error.IsNull()) {
- Exceptions::PropagateError(error);
- }
+ function.SwitchToUnoptimizedCode();
}
- // TODO(srdjan): Handle better complex cases, e.g. when an older optimized
- // code is alive on frame and gets deoptimized after the function was
- // optimized a second time.
- if (FLAG_trace_deopt) {
- OS::Print("After patching ->0x%x:\n", continue_at_pc);
- }
}
+END_LEAF_RUNTIME_ENTRY
// We are entering function name for a valid argument count.
« no previous file with comments | « no previous file | runtime/vm/isolate.h » ('j') | runtime/vm/isolate.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698