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

Unified Diff: runtime/vm/code_generator.cc

Issue 10825236: Replace deopt stubs location/register shuffling with using deopt-info. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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/deopt_instructions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/code_generator.cc
===================================================================
--- runtime/vm/code_generator.cc (revision 10463)
+++ runtime/vm/code_generator.cc (working copy)
@@ -11,11 +11,13 @@
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
+#include "vm/deopt_instructions.h"
#include "vm/exceptions.h"
#include "vm/intermediate_language.h"
#include "vm/object_store.h"
#include "vm/message.h"
#include "vm/message_handler.h"
+#include "vm/parser.h"
#include "vm/resolver.h"
#include "vm/runtime_entry.h"
#include "vm/stack_frame.h"
@@ -1388,10 +1390,11 @@
}
-static void GetDeoptInfo(const Code& code,
- uword pc,
- intptr_t* deopt_id,
- intptr_t* deopt_reason) {
+static void GetDeoptIxDescrAtPc(const Code& code,
+ uword pc,
+ intptr_t* deopt_id,
+ intptr_t* deopt_reason,
+ intptr_t* deopt_index) {
const PcDescriptors& descriptors =
PcDescriptors::Handle(code.pc_descriptors());
ASSERT(!descriptors.IsNull());
@@ -1401,27 +1404,19 @@
(descriptors.DescriptorKind(i) == PcDescriptors::kDeoptIndex)) {
*deopt_id = descriptors.DeoptId(i);
*deopt_reason = descriptors.DeoptReason(i);
+ *deopt_index = descriptors.DeoptIndex(i);
return;
}
}
*deopt_id = Isolate::kNoDeoptId;
*deopt_reason = kDeoptUnknown;
+ *deopt_index = -1;
}
-// Copy saved registers and caller's frame into temporary buffers.
-// Access the deopt information for the deoptimization point.
-// Return the new stack size (including PC marker and deopt return address,
-// excluding FP).
-DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
- intptr_t* saved_registers_address) {
- Isolate* isolate = Isolate::Current();
- Zone zone(isolate);
- HANDLESCOPE(isolate);
- const uword last_fp =
- reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters);
- // Copy saved registers.
+// Copy saved registers into the isolate buffer.
+static void CopySavedRegisters(intptr_t* saved_registers_address) {
intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters];
ASSERT(registers_copy != NULL);
ASSERT(saved_registers_address != NULL);
@@ -1429,55 +1424,137 @@
registers_copy[i] = *saved_registers_address;
saved_registers_address++;
}
- isolate->set_deopt_registers_copy(registers_copy);
- ASSERT(reinterpret_cast<uword>(saved_registers_address) == last_fp);
- DartFrameIterator iterator(last_fp);
- StackFrame* caller_frame = iterator.NextFrame();
- ASSERT(caller_frame != NULL);
- const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
- ASSERT(optimized_code.is_optimized());
+ Isolate::Current()->set_deopt_registers_copy(registers_copy);
+}
- intptr_t deopt_id, deopt_reason;
- GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason);
- ASSERT(deopt_id != Isolate::kNoDeoptId);
- // Add incoming arguments.
+// Copy optimized frame into the isolate buffer.
+// The first incoming argument is stored at the last entry in the
+// copied frame buffer.
+static void CopyFrame(const Code& optimized_code, const StackFrame& frame) {
const Function& function = Function::Handle(optimized_code.function());
- // Think of copied arguments.
+ // Do not copy incoming arguments if there are optional arguments (they
+ // are copied into local space at method entry).
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.
+ // FP, PC-marker and return-address will be copied as well.
const intptr_t frame_copy_size =
1 // Deoptimized function's return address: caller_frame->pc().
- + ((caller_frame->fp() - caller_frame->sp()) / kWordSize)
+ + ((frame.fp() - frame.sp()) / kWordSize)
+ 1 // PC marker.
+ 1 // Caller return address.
+ num_args;
intptr_t* frame_copy = new intptr_t[frame_copy_size];
ASSERT(frame_copy != NULL);
- // Include the return address of deoptimized code.
- intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
+ // Include the return address of optimized code.
+ intptr_t* start = reinterpret_cast<intptr_t*>(frame.sp() - kWordSize);
for (intptr_t i = 0; i < frame_copy_size; i++) {
frame_copy[i] = *(start + i);
}
- isolate->SetDeoptFrameCopy(frame_copy, frame_copy_size);
+ Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size);
+}
+
+
+// Copies saved registers and caller's frame into temporary buffers.
+// Returns the stack size of unoptimzied frame.
+DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
+ intptr_t* saved_registers_address) {
+ Isolate* isolate = Isolate::Current();
+ Zone zone(isolate);
+ HANDLESCOPE(isolate);
+
+ // All registers have been saved below last-fp.
+ const uword last_fp =
+ reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters);
+ CopySavedRegisters(saved_registers_address);
+
+ // Get optimized code and frame that need to be deoptimized.
+ DartFrameIterator iterator(last_fp);
+ StackFrame* caller_frame = iterator.NextFrame();
+ ASSERT(caller_frame != NULL);
+ const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
+ ASSERT(optimized_code.is_optimized());
+
+ intptr_t deopt_id, deopt_reason, deopt_index;
+ GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
+ &deopt_id, &deopt_reason, &deopt_index);
+ ASSERT(deopt_id != Isolate::kNoDeoptId);
+
+ CopyFrame(optimized_code, *caller_frame);
if (FLAG_trace_deopt) {
+ intptr_t deopt_id, deopt_reason, deopt_index;
+ GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
+ &deopt_id, &deopt_reason, &deopt_index);
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());
+ Function::Handle(optimized_code.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;
+
+ // Compute the stack size of unoptimized frame
+ const Array& deopt_info_array =
+ Array::Handle(optimized_code.deopt_info_array());
+ ASSERT(!deopt_info_array.IsNull());
+ DeoptInfo& deopt_info = DeoptInfo::Handle();
+ deopt_info ^= deopt_info_array.At(deopt_index);
+ if (deopt_info.IsNull()) {
+ // TODO(srdjan): Deprecate.
+ // Include the space for return address.
+ intptr_t stack_size_in_bytes = caller_frame->fp() - caller_frame->sp();
+ return stack_size_in_bytes + kWordSize;
+ } else {
+ // For functions with optional argument deoptimization info does not
+ // describe incoming arguments.
+ const Function& function = Function::Handle(optimized_code.function());
+ const intptr_t num_args = (function.num_optional_parameters() > 0) ?
+ 0 : function.num_fixed_parameters();
+ intptr_t unoptimized_stack_size =
+ + deopt_info.Length() - num_args
+ - 2; // Subtract caller FP and PC.
+ return unoptimized_stack_size * kWordSize;
+ }
}
END_LEAF_RUNTIME_ENTRY
+
+static void DeoptimizeWithDeoptInfo(const Code& code,
+ const DeoptInfo& deopt_info,
+ const StackFrame& caller_frame) {
+ const intptr_t len = deopt_info.Length();
+ GrowableArray<DeoptInstr*> deopt_instructions(len);
+ for (intptr_t i = 0; i < len; i++) {
+ deopt_instructions.Add(DeoptInstr::Create(deopt_info.Instruction(i),
+ deopt_info.FromIndex(i)));
+ }
+
+ intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize);
+ const Function& function = Function::Handle(code.function());
+ const intptr_t num_args = (function.num_optional_parameters() > 0) ?
+ 0 : function.num_fixed_parameters();
+ intptr_t to_frame_size =
+ 1 // Deoptimized function's return address.
+ + (caller_frame.fp() - caller_frame.sp()) / kWordSize
+ + 3 // caller-fp, pc, pc-marker.
+ + num_args;
+ DeoptimizationContext deopt_context(start,
+ to_frame_size,
+ Array::Handle(code.object_table()),
+ num_args);
+ for (intptr_t to_index = 0; to_index < len; to_index++) {
+ deopt_instructions[to_index]->Execute(&deopt_context, to_index);
+ }
+ if (FLAG_trace_deopt) {
+ for (intptr_t i = 0; i < len; i++) {
+ OS::Print("*%d. 0x%x [%s]\n",
+ i, start[i], deopt_instructions[i]->ToCString());
+ }
+ }
+}
+
+
// 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) {
@@ -1498,8 +1575,9 @@
intptr_t* frame_copy = isolate->deopt_frame_copy();
intptr_t* registers_copy = isolate->deopt_registers_copy();
- intptr_t deopt_id, deopt_reason;
- GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason);
+ intptr_t deopt_id, deopt_reason, deopt_index;
+ GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
+ &deopt_id, &deopt_reason, &deopt_index);
ASSERT(deopt_id != Isolate::kNoDeoptId);
uword continue_at_pc = unoptimized_code.GetDeoptPcAtDeoptId(deopt_id);
if (FLAG_trace_deopt) {
@@ -1507,19 +1585,34 @@
// 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.
- 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];
+ const Array& deopt_info_array =
+ Array::Handle(optimized_code.deopt_info_array());
+ ASSERT(!deopt_info_array.IsNull());
+ DeoptInfo& deopt_info = DeoptInfo::Handle();
+ deopt_info ^= deopt_info_array.At(deopt_index);
+ if (deopt_info.IsNull()) {
+ // TODO(srdjan): Deprecate.
+ const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size();
+ 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.
+ 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++) {
+ if (FLAG_trace_deopt) {
+ OS::Print("%d. 0x%x\n", i, frame_copy[i]);
+ }
+ *(start + i) = frame_copy[i];
+ }
+ } else {
+ DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame);
}
+
isolate->SetDeoptFrameCopy(NULL, 0);
isolate->set_deopt_registers_copy(NULL);
delete[] frame_copy;
« no previous file with comments | « no previous file | runtime/vm/deopt_instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698