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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/deoptimizer.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 ASSERT(isolate->deoptimizer_data()->current_ == NULL); 92 ASSERT(isolate->deoptimizer_data()->current_ == NULL);
93 isolate->deoptimizer_data()->current_ = deoptimizer; 93 isolate->deoptimizer_data()->current_ = deoptimizer;
94 return deoptimizer; 94 return deoptimizer;
95 } 95 }
96 96
97 97
98 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { 98 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
99 ASSERT(isolate == Isolate::Current()); 99 ASSERT(isolate == Isolate::Current());
100 Deoptimizer* result = isolate->deoptimizer_data()->current_; 100 Deoptimizer* result = isolate->deoptimizer_data()->current_;
101 ASSERT(result != NULL); 101 ASSERT(result != NULL);
102 if (isolate->optimized_handler_patch_buffer() != NULL) {
103 ASSERT(result->bailout_type_ == LAZY);
104 // Before allowing allocation, patch the optimized code back. The
105 // patched code has relocation info that does not agree with the code,
106 // so the patched code should not be seen by the garbage collector.
107 Code* code = result->optimized_code_;
108 DeoptimizationInputData* deopt_data =
109 DeoptimizationInputData::cast(code->deoptimization_data());
110 int deopt_index = isolate->optimized_handler_deopt_index();
111 byte* patch_address =
112 code->instruction_start() + deopt_data->Pc(deopt_index)->value();
113 memcpy(patch_address, isolate->optimized_handler_patch_buffer(),
114 patch_size());
115 // FIXME(mmassi): why doesn't it clear immediately also the patch buffer?
116 isolate->ClearOptimizedHandlerByDeopt(code);
117 }
102 result->DeleteFrameDescriptions(); 118 result->DeleteFrameDescriptions();
103 isolate->deoptimizer_data()->current_ = NULL; 119 isolate->deoptimizer_data()->current_ = NULL;
104 return result; 120 return result;
105 } 121 }
106 122
107 123
108 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { 124 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) {
109 if (jsframe_index == 0) return 0; 125 if (jsframe_index == 0) return 0;
110 126
111 int frame_index = 0; 127 int frame_index = 0;
(...skipping 21 matching lines...) Expand all
133 // Get the function and code from the frame. 149 // Get the function and code from the frame.
134 JSFunction* function = JSFunction::cast(frame->function()); 150 JSFunction* function = JSFunction::cast(frame->function());
135 Code* code = frame->LookupCode(); 151 Code* code = frame->LookupCode();
136 152
137 // Locate the deoptimization point in the code. As we are at a call the 153 // Locate the deoptimization point in the code. As we are at a call the
138 // return address must be at a place in the code with deoptimization support. 154 // return address must be at a place in the code with deoptimization support.
139 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); 155 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
140 int deoptimization_index = safepoint_entry.deoptimization_index(); 156 int deoptimization_index = safepoint_entry.deoptimization_index();
141 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); 157 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
142 158
159 // Find the size of exception handlers.
160 DeoptimizationInputData* deoptimization_data =
161 DeoptimizationInputData::cast(code->deoptimization_data());
162 unsigned handler_count =
163 deoptimization_data->HandlerCount(deoptimization_index)->value();
164 unsigned handler_size = handler_count * StackHandlerConstants::kSize;
165
143 // Always use the actual stack slots when calculating the fp to sp 166 // Always use the actual stack slots when calculating the fp to sp
144 // delta adding two for the function and context. 167 // delta adding two for the function and context.
145 unsigned stack_slots = code->stack_slots(); 168 unsigned stack_slots = code->stack_slots();
146 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize); 169 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize) + handler_size;
147 170
148 Deoptimizer* deoptimizer = new Deoptimizer(isolate, 171 Deoptimizer* deoptimizer = new Deoptimizer(isolate,
149 function, 172 function,
150 Deoptimizer::DEBUGGER, 173 Deoptimizer::DEBUGGER,
151 deoptimization_index, 174 deoptimization_index,
152 frame->pc(), 175 frame->pc(),
153 fp_to_sp_delta, 176 fp_to_sp_delta,
154 code); 177 code);
155 Address tos = frame->fp() - fp_to_sp_delta; 178 Address tos = frame->fp() - fp_to_sp_delta;
156 deoptimizer->FillInputFrame(tos, frame); 179 deoptimizer->FillInputFrame(tos, frame);
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 TranslationIterator iterator(translations, translation_index); 583 TranslationIterator iterator(translations, translation_index);
561 Translation::Opcode opcode = 584 Translation::Opcode opcode =
562 static_cast<Translation::Opcode>(iterator.Next()); 585 static_cast<Translation::Opcode>(iterator.Next());
563 ASSERT(Translation::BEGIN == opcode); 586 ASSERT(Translation::BEGIN == opcode);
564 USE(opcode); 587 USE(opcode);
565 // Read the number of output frames and allocate an array for their 588 // Read the number of output frames and allocate an array for their
566 // descriptions. 589 // descriptions.
567 int count = iterator.Next(); 590 int count = iterator.Next();
568 iterator.Next(); // Drop JS frames count. 591 iterator.Next(); // Drop JS frames count.
569 ASSERT(output_ == NULL); 592 ASSERT(output_ == NULL);
593
594 // If this deoptimization is needed to transfer control to a catch clause
595 // only the first frame is relevant.
596 if (isolate_->optimized_handler_patch_buffer() != NULL) {
597 count = 1;
598 }
599
570 output_ = new FrameDescription*[count]; 600 output_ = new FrameDescription*[count];
571 for (int i = 0; i < count; ++i) { 601 for (int i = 0; i < count; ++i) {
572 output_[i] = NULL; 602 output_[i] = NULL;
573 } 603 }
574 output_count_ = count; 604 output_count_ = count;
575 605
576 // Translate each output frame. 606 // Translate each output frame.
577 for (int i = 0; i < count; ++i) { 607 for (int i = 0; i < count; ++i) {
578 // Read the ast node id, function, and frame height for this output frame. 608 // Read the ast node id, function, and frame height for this output frame.
579 Translation::Opcode opcode = 609 Translation::Opcode opcode =
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 // temporary placeholder in the frame. 847 // temporary placeholder in the frame.
818 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); 848 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
819 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 849 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
820 return; 850 return;
821 } 851 }
822 852
823 case Translation::STACK_SLOT: { 853 case Translation::STACK_SLOT: {
824 int input_slot_index = iterator->Next(); 854 int input_slot_index = iterator->Next();
825 unsigned input_offset = 855 unsigned input_offset =
826 input_->GetOffsetFromSlotIndex(input_slot_index); 856 input_->GetOffsetFromSlotIndex(input_slot_index);
827 intptr_t input_value = input_->GetFrameSlot(input_offset); 857 intptr_t input_value;
858 if (isolate_->optimized_handler_patch_buffer() != NULL &&
859 input_offset >= input_->frame_size()) {
860 // Skip stack slots that were above the handler (they must be
861 // arguments that must be thrown away because try is a statement).
862 input_value = 0;
863 if (FLAG_trace_deopt) {
864 PrintF(" SKIPPING SLOT ABOVE HANDLER (ARGUMENT)\n");
865 }
866 } else {
867 input_value = input_->GetFrameSlot(input_offset);
868 }
828 if (FLAG_trace_deopt) { 869 if (FLAG_trace_deopt) {
829 PrintF(" 0x%08" V8PRIxPTR ": ", 870 PrintF(" 0x%08" V8PRIxPTR ": ",
830 output_[frame_index]->GetTop() + output_offset); 871 output_[frame_index]->GetTop() + output_offset);
831 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", 872 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
832 output_offset, 873 output_offset,
833 input_value, 874 input_value,
834 input_offset); 875 input_offset);
835 reinterpret_cast<Object*>(input_value)->ShortPrint(); 876 reinterpret_cast<Object*>(input_value)->ShortPrint();
836 PrintF("\n"); 877 PrintF("\n");
837 } 878 }
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 1060
1020 switch (opcode) { 1061 switch (opcode) {
1021 case Translation::BEGIN: 1062 case Translation::BEGIN:
1022 case Translation::JS_FRAME: 1063 case Translation::JS_FRAME:
1023 case Translation::ARGUMENTS_ADAPTOR_FRAME: 1064 case Translation::ARGUMENTS_ADAPTOR_FRAME:
1024 case Translation::CONSTRUCT_STUB_FRAME: 1065 case Translation::CONSTRUCT_STUB_FRAME:
1025 case Translation::GETTER_STUB_FRAME: 1066 case Translation::GETTER_STUB_FRAME:
1026 case Translation::SETTER_STUB_FRAME: 1067 case Translation::SETTER_STUB_FRAME:
1027 case Translation::DUPLICATE: 1068 case Translation::DUPLICATE:
1028 UNREACHABLE(); // Malformed input. 1069 UNREACHABLE(); // Malformed input.
1029 return false; 1070 return false;
1030 1071
1031 case Translation::REGISTER: { 1072 case Translation::REGISTER: {
1032 int output_reg = iterator->Next(); 1073 int output_reg = iterator->Next();
1033 if (FLAG_trace_osr) { 1074 if (FLAG_trace_osr) {
1034 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", 1075 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n",
1035 converter.NameOfCPURegister(output_reg), 1076 converter.NameOfCPURegister(output_reg),
1036 input_value, 1077 input_value,
1037 *input_offset); 1078 *input_offset);
1038 } 1079 }
1039 output->SetRegister(output_reg, input_value); 1080 output->SetRegister(output_reg, input_value);
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 RevertStackCheckCodeAt(unoptimized_code, 1267 RevertStackCheckCodeAt(unoptimized_code,
1227 pc_after, 1268 pc_after,
1228 check_code, 1269 check_code,
1229 replacement_code); 1270 replacement_code);
1230 stack_check_cursor += 2 * kIntSize; 1271 stack_check_cursor += 2 * kIntSize;
1231 } 1272 }
1232 } 1273 }
1233 1274
1234 1275
1235 unsigned Deoptimizer::ComputeInputFrameSize() const { 1276 unsigned Deoptimizer::ComputeInputFrameSize() const {
1277 // This is the size of the frame that is the same for both optimized and
1278 // unoptimized frames---the incoming parameters and the fixed part of the
1279 // frame.
1236 unsigned fixed_size = ComputeFixedSize(function_); 1280 unsigned fixed_size = ComputeFixedSize(function_);
1281
1237 // The fp-to-sp delta already takes the context and the function 1282 // The fp-to-sp delta already takes the context and the function
1238 // into account so we have to avoid double counting them (-2). 1283 // into account so we have to avoid double counting them (-2).
1239 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize); 1284 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize);
1285
1240 #ifdef DEBUG 1286 #ifdef DEBUG
1241 if (bailout_type_ == OSR) { 1287 if (bailout_type_ == OSR) {
1242 // TODO(kasperl): It would be nice if we could verify that the 1288 // TODO(kasperl): It would be nice if we could verify that the
1243 // size matches with the stack height we can compute based on the 1289 // size matches with the stack height we can compute based on the
1244 // environment at the OSR entry. The code for that his built into 1290 // environment at the OSR entry. The code for that his built into
1245 // the DoComputeOsrOutputFrame function for now. 1291 // the DoComputeOsrOutputFrame function for now.
1246 } else { 1292 } else {
1247 unsigned stack_slots = optimized_code_->stack_slots(); 1293 // Verify the actual frame size matches the expected (fixed part +
1248 unsigned outgoing_size = ComputeOutgoingArgumentSize(); 1294 // spill slots + exception handlers + outgoing arguments).
1249 ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 1295 unsigned spill_slots_size = optimized_code_->stack_slots() * kPointerSize;
1296 unsigned handlers_size = ComputeHandlersSize();
1297 // If we are doing lazy deoptimization for catching in an optimized
1298 // frame, one of the handlers in the frame description has already been
1299 // dropped by throwing to it.
1300 if (isolate_->optimized_handler_patch_buffer() != NULL) {
1301 ASSERT(bailout_type_ == LAZY);
1302 ASSERT(static_cast<int>(handlers_size) >= StackHandlerConstants::kSize);
1303 handlers_size -= StackHandlerConstants::kSize;
1304 }
1305 unsigned outgoing_arg_size = ComputeOutgoingArgumentSize();
1306 ASSERT(result ==
1307 fixed_size + spill_slots_size + handlers_size + outgoing_arg_size);
1250 } 1308 }
1251 #endif 1309 #endif
1252 return result; 1310 return result;
1253 } 1311 }
1254 1312
1255 1313
1256 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 1314 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
1257 // The fixed part of the frame consists of the return address, frame 1315 // The fixed part of the frame consists of the return address, frame
1258 // pointer, function, context, and all the incoming arguments. 1316 // pointer, function, context, and all the incoming arguments.
1259 return ComputeIncomingArgumentSize(function) + 1317 return ComputeIncomingArgumentSize(function) +
1260 StandardFrameConstants::kFixedFrameSize; 1318 StandardFrameConstants::kFixedFrameSize;
1261 } 1319 }
1262 1320
1263 1321
1264 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 1322 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
1265 // The incoming arguments is the values for formal parameters and 1323 // The incoming arguments is the values for formal parameters and
1266 // the receiver. Every slot contains a pointer. 1324 // the receiver. Every slot contains a pointer.
1267 unsigned arguments = function->shared()->formal_parameter_count() + 1; 1325 unsigned arguments = function->shared()->formal_parameter_count() + 1;
1268 return arguments * kPointerSize; 1326 return arguments * kPointerSize;
1269 } 1327 }
1270 1328
1271 1329
1272 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 1330 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
1331 // Since try is a statement there will not be arguments left on the stack
1332 // once we have popped the handler.
1333 if (isolate_->optimized_handler_patch_buffer() != NULL) {
1334 return 0;
1335 }
1336
1273 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1337 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1274 optimized_code_->deoptimization_data()); 1338 optimized_code_->deoptimization_data());
1275 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 1339 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
1276 return height * kPointerSize; 1340 return height * kPointerSize;
1277 } 1341 }
1278 1342
1279 1343
1344 unsigned Deoptimizer::ComputeHandlersSize() const {
1345 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1346 optimized_code_->deoptimization_data());
1347 unsigned handler_count = data->HandlerCount(bailout_id_)->value();
1348 return handler_count * StackHandlerConstants::kSize;
1349 }
1350
1351
1280 Object* Deoptimizer::ComputeLiteral(int index) const { 1352 Object* Deoptimizer::ComputeLiteral(int index) const {
1281 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1353 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1282 optimized_code_->deoptimization_data()); 1354 optimized_code_->deoptimization_data());
1283 FixedArray* literals = data->LiteralArray(); 1355 FixedArray* literals = data->LiteralArray();
1284 return literals->get(index); 1356 return literals->get(index);
1285 } 1357 }
1286 1358
1287 1359
1288 void Deoptimizer::AddDoubleValue(intptr_t slot_address, 1360 void Deoptimizer::AddDoubleValue(intptr_t slot_address,
1289 double value) { 1361 double value) {
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1501 1573
1502 void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) { 1574 void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
1503 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone()); 1575 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
1504 buffer_->Add(literal_id, zone()); 1576 buffer_->Add(literal_id, zone());
1505 buffer_->Add(height, zone()); 1577 buffer_->Add(height, zone());
1506 } 1578 }
1507 1579
1508 1580
1509 void Translation::BeginJSFrame(BailoutId node_id, 1581 void Translation::BeginJSFrame(BailoutId node_id,
1510 int literal_id, 1582 int literal_id,
1511 unsigned height) { 1583 unsigned height,
1584 int handler_count) {
1512 buffer_->Add(JS_FRAME, zone()); 1585 buffer_->Add(JS_FRAME, zone());
1513 buffer_->Add(node_id.ToInt(), zone()); 1586 buffer_->Add(node_id.ToInt(), zone());
1514 buffer_->Add(literal_id, zone()); 1587 buffer_->Add(literal_id, zone());
1515 buffer_->Add(height, zone()); 1588 buffer_->Add(height, zone());
1589 buffer_->Add(handler_count, zone());
1516 } 1590 }
1517 1591
1518 1592
1519 void Translation::StoreRegister(Register reg) { 1593 void Translation::StoreRegister(Register reg) {
1520 buffer_->Add(REGISTER, zone()); 1594 buffer_->Add(REGISTER, zone());
1521 buffer_->Add(reg.code(), zone()); 1595 buffer_->Add(reg.code(), zone());
1522 } 1596 }
1523 1597
1524 1598
1525 void Translation::StoreInt32Register(Register reg) { 1599 void Translation::StoreInt32Register(Register reg) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 case INT32_STACK_SLOT: 1669 case INT32_STACK_SLOT:
1596 case UINT32_STACK_SLOT: 1670 case UINT32_STACK_SLOT:
1597 case DOUBLE_STACK_SLOT: 1671 case DOUBLE_STACK_SLOT:
1598 case LITERAL: 1672 case LITERAL:
1599 return 1; 1673 return 1;
1600 case BEGIN: 1674 case BEGIN:
1601 case ARGUMENTS_ADAPTOR_FRAME: 1675 case ARGUMENTS_ADAPTOR_FRAME:
1602 case CONSTRUCT_STUB_FRAME: 1676 case CONSTRUCT_STUB_FRAME:
1603 return 2; 1677 return 2;
1604 case JS_FRAME: 1678 case JS_FRAME:
1605 return 3; 1679 return 4;
1606 } 1680 }
1607 UNREACHABLE(); 1681 UNREACHABLE();
1608 return -1; 1682 return -1;
1609 } 1683 }
1610 1684
1611 1685
1612 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 1686 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
1613 1687
1614 const char* Translation::StringFor(Opcode opcode) { 1688 const char* Translation::StringFor(Opcode opcode) {
1615 switch (opcode) { 1689 switch (opcode) {
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 1929
1856 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { 1930 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
1857 v->VisitPointer(BitCast<Object**>(&function_)); 1931 v->VisitPointer(BitCast<Object**>(&function_));
1858 v->VisitPointers(parameters_, parameters_ + parameters_count_); 1932 v->VisitPointers(parameters_, parameters_ + parameters_count_);
1859 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); 1933 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
1860 } 1934 }
1861 1935
1862 #endif // ENABLE_DEBUGGER_SUPPORT 1936 #endif // ENABLE_DEBUGGER_SUPPORT
1863 1937
1864 } } // namespace v8::internal 1938 } } // namespace v8::internal
OLDNEW
« 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