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

Unified Diff: src/deoptimizer.cc

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 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 | « src/deoptimizer.h ('k') | src/diy-fp.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/deoptimizer.cc
===================================================================
--- src/deoptimizer.cc (revision 8618)
+++ src/deoptimizer.cc (working copy)
@@ -1,4 +1,4 @@
-// Copyright 2010 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -44,6 +44,9 @@
lazy_deoptimization_entry_code_ = NULL;
current_ = NULL;
deoptimizing_code_list_ = NULL;
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ deoptimized_frame_info_ = NULL;
+#endif
}
@@ -60,6 +63,16 @@
}
}
+
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void DeoptimizerData::Iterate(ObjectVisitor* v) {
+ if (deoptimized_frame_info_ != NULL) {
+ deoptimized_frame_info_->Iterate(v);
+ }
+}
+#endif
+
+
Deoptimizer* Deoptimizer::New(JSFunction* function,
BailoutType type,
unsigned bailout_id,
@@ -72,7 +85,8 @@
type,
bailout_id,
from,
- fp_to_sp_delta);
+ fp_to_sp_delta,
+ NULL);
ASSERT(isolate->deoptimizer_data()->current_ == NULL);
isolate->deoptimizer_data()->current_ = deoptimizer;
return deoptimizer;
@@ -88,7 +102,92 @@
return result;
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
+DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
+ JavaScriptFrame* frame,
+ int frame_index,
+ Isolate* isolate) {
+ ASSERT(isolate == Isolate::Current());
+ ASSERT(frame->is_optimized());
+ ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == NULL);
+ // Get the function and code from the frame.
+ JSFunction* function = JSFunction::cast(frame->function());
+ Code* code = frame->LookupCode();
+ Address code_start_address = code->instruction_start();
+
+ // Locate the deoptimization point in the code. As we are at a call the
+ // return address must be at a place in the code with deoptimization support.
+ int deoptimization_index = Safepoint::kNoDeoptimizationIndex;
+ // Scope this as the safe point constructor will disallow allocation.
+ {
+ SafepointTable table(code);
+ for (unsigned i = 0; i < table.length(); ++i) {
+ Address address = code_start_address + table.GetPcOffset(i);
+ if (address == frame->pc()) {
+ SafepointEntry safepoint_entry = table.GetEntry(i);
+ ASSERT(safepoint_entry.deoptimization_index() !=
+ Safepoint::kNoDeoptimizationIndex);
+ deoptimization_index = safepoint_entry.deoptimization_index();
+ break;
+ }
+ }
+ }
+ ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
+
+ // Always use the actual stack slots when calculating the fp to sp
+ // delta adding two for the function and context.
+ unsigned stack_slots = code->stack_slots();
+ unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize);
+
+ Deoptimizer* deoptimizer = new Deoptimizer(isolate,
+ function,
+ Deoptimizer::DEBUGGER,
+ deoptimization_index,
+ frame->pc(),
+ fp_to_sp_delta,
+ code);
+ Address tos = frame->fp() - fp_to_sp_delta;
+ deoptimizer->FillInputFrame(tos, frame);
+
+ // Calculate the output frames.
+ Deoptimizer::ComputeOutputFrames(deoptimizer);
+
+ // Create the GC safe output frame information and register it for GC
+ // handling.
+ ASSERT_LT(frame_index, deoptimizer->output_count());
+ DeoptimizedFrameInfo* info =
+ new DeoptimizedFrameInfo(deoptimizer, frame_index);
+ isolate->deoptimizer_data()->deoptimized_frame_info_ = info;
+
+ // Get the "simulated" top and size for the requested frame.
+ Address top =
+ reinterpret_cast<Address>(deoptimizer->output_[frame_index]->GetTop());
+ uint32_t size = deoptimizer->output_[frame_index]->GetFrameSize();
+
+ // Done with the GC-unsafe frame descriptions. This re-enables allocation.
+ deoptimizer->DeleteFrameDescriptions();
+
+ // Allocate a heap number for the doubles belonging to this frame.
+ deoptimizer->MaterializeHeapNumbersForDebuggerInspectableFrame(
+ top, size, info);
+
+ // Finished using the deoptimizer instance.
+ delete deoptimizer;
+
+ return info;
+}
+
+
+void Deoptimizer::DeleteDebuggerInspectableFrame(DeoptimizedFrameInfo* info,
+ Isolate* isolate) {
+ ASSERT(isolate == Isolate::Current());
+ ASSERT(isolate->deoptimizer_data()->deoptimized_frame_info_ == info);
+ delete info;
+ isolate->deoptimizer_data()->deoptimized_frame_info_ = NULL;
+}
+#endif
+
void Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
int count,
BailoutType type) {
@@ -211,18 +310,24 @@
BailoutType type,
unsigned bailout_id,
Address from,
- int fp_to_sp_delta)
+ int fp_to_sp_delta,
+ Code* optimized_code)
: isolate_(isolate),
function_(function),
bailout_id_(bailout_id),
bailout_type_(type),
from_(from),
fp_to_sp_delta_(fp_to_sp_delta),
+ input_(NULL),
output_count_(0),
output_(NULL),
deferred_heap_numbers_(0) {
if (FLAG_trace_deopt && type != OSR) {
- PrintF("**** DEOPT: ");
+ if (type == DEBUGGER) {
+ PrintF("**** DEOPT FOR DEBUGGER: ");
+ } else {
+ PrintF("**** DEOPT: ");
+ }
function->PrintName();
PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n",
bailout_id,
@@ -250,10 +355,16 @@
optimized_code_ = function_->code();
ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION);
ASSERT(!optimized_code_->contains(from));
+ } else if (type == DEBUGGER) {
+ optimized_code_ = optimized_code;
+ ASSERT(optimized_code_->contains(from));
}
ASSERT(HEAP->allow_allocation(false));
unsigned size = ComputeInputFrameSize();
input_ = new(size) FrameDescription(size, function);
+#ifdef DEBUG
+ input_->SetKind(Code::OPTIMIZED_FUNCTION);
+#endif
}
@@ -419,6 +530,7 @@
void Deoptimizer::MaterializeHeapNumbers() {
+ ASSERT_NE(DEBUGGER, bailout_type_);
for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
Handle<Object> num = isolate_->factory()->NewNumber(d.value());
@@ -434,6 +546,47 @@
}
+#ifdef ENABLE_DEBUGGER_SUPPORT
+void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
+ Address top, uint32_t size, DeoptimizedFrameInfo* info) {
+ ASSERT_EQ(DEBUGGER, bailout_type_);
+ for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
+ HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
+
+ // Check of the heap number to materialize actually belong to the frame
+ // being extracted.
+ Address slot = d.slot_address();
+ if (top <= slot && slot < top + size) {
+ Handle<Object> num = isolate_->factory()->NewNumber(d.value());
+ // Calculate the index with the botton of the expression stack
+ // at index 0, and the fixed part (including incoming arguments)
+ // at negative indexes.
+ int index = static_cast<int>(
+ info->expression_count_ - (slot - top) / kPointerSize - 1);
+ if (FLAG_trace_deopt) {
+ PrintF("Materializing a new heap number %p [%e] in slot %p"
+ "for stack index %d\n",
+ reinterpret_cast<void*>(*num),
+ d.value(),
+ d.slot_address(),
+ index);
+ }
+ if (index >=0) {
+ info->SetExpression(index, *num);
+ } else {
+ // Calculate parameter index subtracting one for the receiver.
+ int parameter_index =
+ index +
+ static_cast<int>(size) / kPointerSize -
+ info->expression_count_ - 1;
+ info->SetParameter(parameter_index, *num);
+ }
+ }
+ }
+}
+#endif
+
+
void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
int frame_index,
unsigned output_offset) {
@@ -909,6 +1062,9 @@
Isolate::Current()->memory_allocator()->AllocateChunk(desc.instr_size,
EXECUTABLE,
NULL);
+ if (chunk == NULL) {
+ V8::FatalProcessOutOfMemory("Not enough memory for deoptimization table");
+ }
memcpy(chunk->body(), desc.buffer, desc.instr_size);
CPU::FlushICache(chunk->body(), desc.instr_size);
return chunk;
@@ -977,18 +1133,48 @@
if (slot_index >= 0) {
// Local or spill slots. Skip the fixed part of the frame
// including all arguments.
- unsigned base = static_cast<unsigned>(
- GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()));
+ unsigned base =
+ GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction());
return base - ((slot_index + 1) * kPointerSize);
} else {
// Incoming parameter.
- unsigned base = static_cast<unsigned>(GetFrameSize() -
- deoptimizer->ComputeIncomingArgumentSize(GetFunction()));
+ unsigned base = GetFrameSize() -
+ deoptimizer->ComputeIncomingArgumentSize(GetFunction());
return base - ((slot_index + 1) * kPointerSize);
}
}
+int FrameDescription::ComputeParametersCount() {
+ return function_->shared()->formal_parameter_count();
+}
+
+
+Object* FrameDescription::GetParameter(Deoptimizer* deoptimizer, int index) {
+ ASSERT_EQ(Code::FUNCTION, kind_);
+ ASSERT(index >= 0);
+ ASSERT(index < ComputeParametersCount());
+ // The slot indexes for incoming arguments are negative.
+ unsigned offset = GetOffsetFromSlotIndex(deoptimizer,
+ index - ComputeParametersCount());
+ return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
+}
+
+
+unsigned FrameDescription::GetExpressionCount(Deoptimizer* deoptimizer) {
+ ASSERT_EQ(Code::FUNCTION, kind_);
+ unsigned size = GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction());
+ return size / kPointerSize;
+}
+
+
+Object* FrameDescription::GetExpression(Deoptimizer* deoptimizer, int index) {
+ ASSERT_EQ(Code::FUNCTION, kind_);
+ unsigned offset = GetOffsetFromSlotIndex(deoptimizer, index);
+ return reinterpret_cast<Object*>(*GetFrameSlotPointer(offset));
+}
+
+
void TranslationBuffer::Add(int32_t value) {
// Encode the sign bit in the least significant bit.
bool is_negative = (value < 0);
@@ -1112,7 +1298,7 @@
}
-#ifdef OBJECT_PRINT
+#if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
const char* Translation::StringFor(Opcode opcode) {
switch (opcode) {
@@ -1261,4 +1447,33 @@
}
+DeoptimizedFrameInfo::DeoptimizedFrameInfo(
+ Deoptimizer* deoptimizer, int frame_index) {
+ FrameDescription* output_frame = deoptimizer->output_[frame_index];
+ SetFunction(output_frame->GetFunction());
+ expression_count_ = output_frame->GetExpressionCount(deoptimizer);
+ parameters_count_ = output_frame->ComputeParametersCount();
+ parameters_ = new Object*[parameters_count_];
+ for (int i = 0; i < parameters_count_; i++) {
+ SetParameter(i, output_frame->GetParameter(deoptimizer, i));
+ }
+ expression_stack_ = new Object*[expression_count_];
+ for (int i = 0; i < expression_count_; i++) {
+ SetExpression(i, output_frame->GetExpression(deoptimizer, i));
+ }
+}
+
+
+DeoptimizedFrameInfo::~DeoptimizedFrameInfo() {
+ delete[] expression_stack_;
+ delete[] parameters_;
+}
+
+void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
+ v->VisitPointer(reinterpret_cast<Object**>(&function_));
+ v->VisitPointers(parameters_, parameters_ + parameters_count_);
+ v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
+}
+
+
} } // namespace v8::internal
« no previous file with comments | « src/deoptimizer.h ('k') | src/diy-fp.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698