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

Unified Diff: src/deoptimizer.cc

Issue 10910161: Partial ia32 implementation of optimized try/catch (by Kevin Millikin) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fixed build. Created 8 years, 3 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/flag-definitions.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/deoptimizer.cc
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index d1b00f8bdea718a71eca5d12d47900cd2f677883..aa8c1503a04851393e5d00f9298f0537cbdbd0a6 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -99,6 +99,22 @@ Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
ASSERT(isolate == Isolate::Current());
Deoptimizer* result = isolate->deoptimizer_data()->current_;
ASSERT(result != NULL);
+ if (isolate->optimized_handler_patch_buffer() != NULL) {
+ ASSERT(result->bailout_type_ == LAZY);
+ // Before allowing allocation, patch the optimized code back. The
+ // patched code has relocation info that does not agree with the code,
+ // so the patched code should not be seen by the garbage collector.
+ Code* code = result->optimized_code_;
+ DeoptimizationInputData* deopt_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ int deopt_index = isolate->optimized_handler_deopt_index();
+ byte* patch_address =
+ code->instruction_start() + deopt_data->Pc(deopt_index)->value();
+ memcpy(patch_address, isolate->optimized_handler_patch_buffer(),
+ patch_size());
+ // FIXME(mmassi): why doesn't it clear immediately also the patch buffer?
+ isolate->ClearOptimizedHandlerByDeopt(code);
+ }
result->DeleteFrameDescriptions();
isolate->deoptimizer_data()->current_ = NULL;
return result;
@@ -140,10 +156,17 @@ DeoptimizedFrameInfo* Deoptimizer::DebuggerInspectableFrame(
int deoptimization_index = safepoint_entry.deoptimization_index();
ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
+ // Find the size of exception handlers.
+ DeoptimizationInputData* deoptimization_data =
+ DeoptimizationInputData::cast(code->deoptimization_data());
+ unsigned handler_count =
+ deoptimization_data->HandlerCount(deoptimization_index)->value();
+ unsigned handler_size = handler_count * StackHandlerConstants::kSize;
+
// 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);
+ unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize) + handler_size;
Deoptimizer* deoptimizer = new Deoptimizer(isolate,
function,
@@ -567,6 +590,13 @@ void Deoptimizer::DoComputeOutputFrames() {
int count = iterator.Next();
iterator.Next(); // Drop JS frames count.
ASSERT(output_ == NULL);
+
+ // If this deoptimization is needed to transfer control to a catch clause
+ // only the first frame is relevant.
+ if (isolate_->optimized_handler_patch_buffer() != NULL) {
+ count = 1;
+ }
+
output_ = new FrameDescription*[count];
for (int i = 0; i < count; ++i) {
output_[i] = NULL;
@@ -824,7 +854,18 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
int input_slot_index = iterator->Next();
unsigned input_offset =
input_->GetOffsetFromSlotIndex(input_slot_index);
- intptr_t input_value = input_->GetFrameSlot(input_offset);
+ intptr_t input_value;
+ if (isolate_->optimized_handler_patch_buffer() != NULL &&
+ input_offset >= input_->frame_size()) {
+ // Skip stack slots that were above the handler (they must be
+ // arguments that must be thrown away because try is a statement).
+ input_value = 0;
+ if (FLAG_trace_deopt) {
+ PrintF(" SKIPPING SLOT ABOVE HANDLER (ARGUMENT)\n");
+ }
+ } else {
+ input_value = input_->GetFrameSlot(input_offset);
+ }
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": ",
output_[frame_index]->GetTop() + output_offset);
@@ -1026,7 +1067,7 @@ bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
case Translation::SETTER_STUB_FRAME:
case Translation::DUPLICATE:
UNREACHABLE(); // Malformed input.
- return false;
+ return false;
case Translation::REGISTER: {
int output_reg = iterator->Next();
@@ -1233,10 +1274,15 @@ void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
unsigned Deoptimizer::ComputeInputFrameSize() const {
+ // This is the size of the frame that is the same for both optimized and
+ // unoptimized frames---the incoming parameters and the fixed part of the
+ // frame.
unsigned fixed_size = ComputeFixedSize(function_);
+
// The fp-to-sp delta already takes the context and the function
// into account so we have to avoid double counting them (-2).
unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize);
+
#ifdef DEBUG
if (bailout_type_ == OSR) {
// TODO(kasperl): It would be nice if we could verify that the
@@ -1244,9 +1290,21 @@ unsigned Deoptimizer::ComputeInputFrameSize() const {
// environment at the OSR entry. The code for that his built into
// the DoComputeOsrOutputFrame function for now.
} else {
- unsigned stack_slots = optimized_code_->stack_slots();
- unsigned outgoing_size = ComputeOutgoingArgumentSize();
- ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
+ // Verify the actual frame size matches the expected (fixed part +
+ // spill slots + exception handlers + outgoing arguments).
+ unsigned spill_slots_size = optimized_code_->stack_slots() * kPointerSize;
+ unsigned handlers_size = ComputeHandlersSize();
+ // If we are doing lazy deoptimization for catching in an optimized
+ // frame, one of the handlers in the frame description has already been
+ // dropped by throwing to it.
+ if (isolate_->optimized_handler_patch_buffer() != NULL) {
+ ASSERT(bailout_type_ == LAZY);
+ ASSERT(static_cast<int>(handlers_size) >= StackHandlerConstants::kSize);
+ handlers_size -= StackHandlerConstants::kSize;
+ }
+ unsigned outgoing_arg_size = ComputeOutgoingArgumentSize();
+ ASSERT(result ==
+ fixed_size + spill_slots_size + handlers_size + outgoing_arg_size);
}
#endif
return result;
@@ -1270,6 +1328,12 @@ unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
+ // Since try is a statement there will not be arguments left on the stack
+ // once we have popped the handler.
+ if (isolate_->optimized_handler_patch_buffer() != NULL) {
+ return 0;
+ }
+
DeoptimizationInputData* data = DeoptimizationInputData::cast(
optimized_code_->deoptimization_data());
unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
@@ -1277,6 +1341,14 @@ unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
}
+unsigned Deoptimizer::ComputeHandlersSize() const {
+ DeoptimizationInputData* data = DeoptimizationInputData::cast(
+ optimized_code_->deoptimization_data());
+ unsigned handler_count = data->HandlerCount(bailout_id_)->value();
+ return handler_count * StackHandlerConstants::kSize;
+}
+
+
Object* Deoptimizer::ComputeLiteral(int index) const {
DeoptimizationInputData* data = DeoptimizationInputData::cast(
optimized_code_->deoptimization_data());
@@ -1508,11 +1580,13 @@ void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
void Translation::BeginJSFrame(BailoutId node_id,
int literal_id,
- unsigned height) {
+ unsigned height,
+ int handler_count) {
buffer_->Add(JS_FRAME, zone());
buffer_->Add(node_id.ToInt(), zone());
buffer_->Add(literal_id, zone());
buffer_->Add(height, zone());
+ buffer_->Add(handler_count, zone());
}
@@ -1602,7 +1676,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
case CONSTRUCT_STUB_FRAME:
return 2;
case JS_FRAME:
- return 3;
+ return 4;
}
UNREACHABLE();
return -1;
« no previous file with comments | « src/deoptimizer.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698