OLD | NEW |
---|---|
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 |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "accessors.h" | |
30 #include "codegen.h" | 31 #include "codegen.h" |
31 #include "deoptimizer.h" | 32 #include "deoptimizer.h" |
32 #include "disasm.h" | 33 #include "disasm.h" |
33 #include "full-codegen.h" | 34 #include "full-codegen.h" |
34 #include "global-handles.h" | 35 #include "global-handles.h" |
35 #include "macro-assembler.h" | 36 #include "macro-assembler.h" |
36 #include "prettyprinter.h" | 37 #include "prettyprinter.h" |
37 | 38 |
38 | 39 |
39 namespace v8 { | 40 namespace v8 { |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
361 function_(function), | 362 function_(function), |
362 bailout_id_(bailout_id), | 363 bailout_id_(bailout_id), |
363 bailout_type_(type), | 364 bailout_type_(type), |
364 from_(from), | 365 from_(from), |
365 fp_to_sp_delta_(fp_to_sp_delta), | 366 fp_to_sp_delta_(fp_to_sp_delta), |
366 has_alignment_padding_(0), | 367 has_alignment_padding_(0), |
367 input_(NULL), | 368 input_(NULL), |
368 output_count_(0), | 369 output_count_(0), |
369 jsframe_count_(0), | 370 jsframe_count_(0), |
370 output_(NULL), | 371 output_(NULL), |
372 deferred_arguments_objects_values_(0), | |
373 deferred_arguments_objects_(0), | |
371 deferred_heap_numbers_(0) { | 374 deferred_heap_numbers_(0) { |
372 if (FLAG_trace_deopt && type != OSR) { | 375 if (FLAG_trace_deopt && type != OSR) { |
373 if (type == DEBUGGER) { | 376 if (type == DEBUGGER) { |
374 PrintF("**** DEOPT FOR DEBUGGER: "); | 377 PrintF("**** DEOPT FOR DEBUGGER: "); |
375 } else { | 378 } else { |
376 PrintF("**** DEOPT: "); | 379 PrintF("**** DEOPT: "); |
377 } | 380 } |
378 function->PrintName(); | 381 function->PrintName(); |
379 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 382 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
380 bailout_id, | 383 bailout_id, |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
626 output_[index]->GetPc(), | 629 output_[index]->GetPc(), |
627 FullCodeGenerator::State2String( | 630 FullCodeGenerator::State2String( |
628 static_cast<FullCodeGenerator::State>( | 631 static_cast<FullCodeGenerator::State>( |
629 output_[index]->GetState()->value())), | 632 output_[index]->GetState()->value())), |
630 has_alignment_padding_ ? "with padding" : "no padding", | 633 has_alignment_padding_ ? "with padding" : "no padding", |
631 ms); | 634 ms); |
632 } | 635 } |
633 } | 636 } |
634 | 637 |
635 | 638 |
636 void Deoptimizer::MaterializeHeapNumbers() { | 639 static void MaterializeArgumentsObjectUsingOutputFrame( |
640 Isolate* isolate, JavaScriptFrame* frame) { | |
641 Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate); | |
642 Handle<Object> arguments; | |
643 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { | |
644 if (frame->GetExpression(i) == isolate->heap()->arguments_marker()) { | |
645 if (arguments.is_null()) { | |
646 // FunctionGetArguments can't throw an exception, so cast away the | |
647 // doubt with an assert. | |
648 arguments = Handle<Object>( | |
649 Accessors::FunctionGetArguments(*function, | |
650 NULL)->ToObjectUnchecked()); | |
651 ASSERT(*arguments != isolate->heap()->null_value()); | |
652 ASSERT(*arguments != isolate->heap()->undefined_value()); | |
653 } | |
654 frame->SetExpression(i, *arguments); | |
655 if (FLAG_trace_deopt) { | |
656 PrintF("Materializing arguments object for frame %p - %p: ", | |
657 reinterpret_cast<void*>(frame->sp()), | |
658 reinterpret_cast<void*>(frame->fp())); | |
659 arguments->ShortPrint(); | |
660 PrintF("\n"); | |
661 } | |
662 } | |
663 } | |
664 } | |
665 | |
666 | |
667 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | |
637 ASSERT_NE(DEBUGGER, bailout_type_); | 668 ASSERT_NE(DEBUGGER, bailout_type_); |
669 | |
670 // Handlify all argument object values before triggering any allocation. | |
671 List<Handle<Object> > values(deferred_arguments_objects_values_.length()); | |
672 for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) { | |
673 values.Add(Handle<Object>(deferred_arguments_objects_values_[i])); | |
674 } | |
675 | |
676 // Play it safe and clear all unhandlified values before we continue. | |
677 deferred_arguments_objects_values_.Clear(); | |
678 | |
679 // Materialize all heap numbers before looking at arguments. | |
Sven Panne
2012/09/12 07:14:22
Describe why this is necessary to do before argume
Michael Starzinger
2012/09/12 10:07:28
Done.
| |
638 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 680 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
639 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 681 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
640 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 682 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
641 if (FLAG_trace_deopt) { | 683 if (FLAG_trace_deopt) { |
642 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | 684 PrintF("Materializing a new heap number %p [%e] in slot %p\n", |
643 reinterpret_cast<void*>(*num), | 685 reinterpret_cast<void*>(*num), |
644 d.value(), | 686 d.value(), |
645 d.slot_address()); | 687 d.slot_address()); |
646 } | 688 } |
647 | |
648 Memory::Object_at(d.slot_address()) = *num; | 689 Memory::Object_at(d.slot_address()) = *num; |
649 } | 690 } |
691 | |
692 // Materialize arguments objects one frame at a time. | |
693 int values_index = 0; | |
694 int arguments_index = 0; | |
695 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { | |
696 if (frame_index != 0) it->Advance(); | |
697 JavaScriptFrame* frame = it->frame(); | |
698 Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate_); | |
699 Handle<JSObject> arguments; | |
700 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { | |
701 if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) { | |
702 ArgumentsObjectMaterializationDescriptor descriptor = | |
703 deferred_arguments_objects_[arguments_index++]; | |
704 const int length = descriptor.arguments_length(); | |
705 if (arguments.is_null()) { | |
706 // Construct an arguments object and copy the parameters to a newly | |
707 // allocated arguments object backing store. | |
708 arguments = isolate_->factory()->NewArgumentsObject(function, length); | |
709 Handle<FixedArray> array = isolate_->factory()->NewFixedArray(length); | |
710 ASSERT(array->length() == length); | |
711 for (int i = 0; i < length; ++i) { | |
712 array->set(i, *values[values_index++]); | |
713 } | |
714 arguments->set_elements(*array); | |
715 } else { | |
716 values_index += length; | |
717 } | |
718 if (!frame->has_adapted_arguments()) { | |
Sven Panne
2012/09/12 07:14:22
Can rearrange things a bit here so that we have a
Michael Starzinger
2012/09/12 10:07:28
Done. I removed the static helper method completel
| |
719 frame->SetExpression(i, *arguments); | |
720 if (FLAG_trace_deopt) { | |
721 PrintF("Materializing arguments object for %p: ", | |
722 reinterpret_cast<void*>(descriptor.slot_address())); | |
723 arguments->ShortPrint(); | |
724 PrintF("\n"); | |
725 } | |
726 } | |
727 } | |
728 } | |
729 if (frame->has_adapted_arguments()) { | |
730 MaterializeArgumentsObjectUsingOutputFrame(isolate_, frame); | |
731 } | |
732 } | |
733 ASSERT_EQ(values_index, values.length()); | |
734 ASSERT_EQ(arguments_index, deferred_arguments_objects_.length()); | |
650 } | 735 } |
651 | 736 |
652 | 737 |
653 #ifdef ENABLE_DEBUGGER_SUPPORT | 738 #ifdef ENABLE_DEBUGGER_SUPPORT |
654 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 739 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
655 Address parameters_top, | 740 Address parameters_top, |
656 uint32_t parameters_size, | 741 uint32_t parameters_size, |
657 Address expressions_top, | 742 Address expressions_top, |
658 uint32_t expressions_size, | 743 uint32_t expressions_size, |
659 DeoptimizedFrameInfo* info) { | 744 DeoptimizedFrameInfo* info) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
925 output_offset); | 1010 output_offset); |
926 literal->ShortPrint(); | 1011 literal->ShortPrint(); |
927 PrintF(" ; literal\n"); | 1012 PrintF(" ; literal\n"); |
928 } | 1013 } |
929 intptr_t value = reinterpret_cast<intptr_t>(literal); | 1014 intptr_t value = reinterpret_cast<intptr_t>(literal); |
930 output_[frame_index]->SetFrameSlot(output_offset, value); | 1015 output_[frame_index]->SetFrameSlot(output_offset, value); |
931 return; | 1016 return; |
932 } | 1017 } |
933 | 1018 |
934 case Translation::ARGUMENTS_OBJECT: { | 1019 case Translation::ARGUMENTS_OBJECT: { |
935 // Use the arguments marker value as a sentinel and fill in the arguments | 1020 int args_index = iterator->Next() + 1; // Skip receiver. |
936 // object after the deoptimized frame is built. | 1021 int args_length = iterator->Next() - 1; // Skip receiver. |
937 if (FLAG_trace_deopt) { | 1022 if (FLAG_trace_deopt) { |
938 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", | 1023 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", |
939 output_[frame_index]->GetTop() + output_offset, | 1024 output_[frame_index]->GetTop() + output_offset, |
940 output_offset); | 1025 output_offset); |
941 isolate_->heap()->arguments_marker()->ShortPrint(); | 1026 isolate_->heap()->arguments_marker()->ShortPrint(); |
942 PrintF(" ; arguments object\n"); | 1027 PrintF(" ; arguments object\n"); |
943 } | 1028 } |
1029 // Use the arguments marker value as a sentinel and fill in the arguments | |
1030 // object after the deoptimized frame is built. | |
944 intptr_t value = reinterpret_cast<intptr_t>( | 1031 intptr_t value = reinterpret_cast<intptr_t>( |
945 isolate_->heap()->arguments_marker()); | 1032 isolate_->heap()->arguments_marker()); |
1033 AddArgumentsObject( | |
1034 output_[frame_index]->GetTop() + output_offset, args_length); | |
946 output_[frame_index]->SetFrameSlot(output_offset, value); | 1035 output_[frame_index]->SetFrameSlot(output_offset, value); |
1036 // We save the tagged argument values on the side and materialize the | |
1037 // actual arguments object after the deoptimized frame is built. | |
1038 for (int i = 0; i < args_length; i++) { | |
1039 unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i); | |
1040 intptr_t input_value = input_->GetFrameSlot(input_offset); | |
1041 AddArgumentsObjectValue(input_value); | |
1042 } | |
947 return; | 1043 return; |
948 } | 1044 } |
949 } | 1045 } |
950 } | 1046 } |
951 | 1047 |
952 | 1048 |
953 static bool ObjectToInt32(Object* obj, int32_t* value) { | 1049 static bool ObjectToInt32(Object* obj, int32_t* value) { |
954 if (obj->IsSmi()) { | 1050 if (obj->IsSmi()) { |
955 *value = Smi::cast(obj)->value(); | 1051 *value = Smi::cast(obj)->value(); |
956 return true; | 1052 return true; |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1278 | 1374 |
1279 | 1375 |
1280 Object* Deoptimizer::ComputeLiteral(int index) const { | 1376 Object* Deoptimizer::ComputeLiteral(int index) const { |
1281 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 1377 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
1282 optimized_code_->deoptimization_data()); | 1378 optimized_code_->deoptimization_data()); |
1283 FixedArray* literals = data->LiteralArray(); | 1379 FixedArray* literals = data->LiteralArray(); |
1284 return literals->get(index); | 1380 return literals->get(index); |
1285 } | 1381 } |
1286 | 1382 |
1287 | 1383 |
1288 void Deoptimizer::AddDoubleValue(intptr_t slot_address, | 1384 void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) { |
1289 double value) { | 1385 ArgumentsObjectMaterializationDescriptor object_desc( |
1386 reinterpret_cast<Address>(slot_address), argc); | |
1387 deferred_arguments_objects_.Add(object_desc); | |
1388 } | |
1389 | |
1390 | |
1391 void Deoptimizer::AddArgumentsObjectValue(intptr_t value) { | |
1392 deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value)); | |
1393 } | |
1394 | |
1395 | |
1396 void Deoptimizer::AddDoubleValue(intptr_t slot_address, double value) { | |
1290 HeapNumberMaterializationDescriptor value_desc( | 1397 HeapNumberMaterializationDescriptor value_desc( |
1291 reinterpret_cast<Address>(slot_address), value); | 1398 reinterpret_cast<Address>(slot_address), value); |
1292 deferred_heap_numbers_.Add(value_desc); | 1399 deferred_heap_numbers_.Add(value_desc); |
1293 } | 1400 } |
1294 | 1401 |
1295 | 1402 |
1296 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { | 1403 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { |
1297 // We cannot run this if the serializer is enabled because this will | 1404 // We cannot run this if the serializer is enabled because this will |
1298 // cause us to emit relocation information for the external | 1405 // cause us to emit relocation information for the external |
1299 // references. This is fine because the deoptimizer's code section | 1406 // references. This is fine because the deoptimizer's code section |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1563 buffer_->Add(index, zone()); | 1670 buffer_->Add(index, zone()); |
1564 } | 1671 } |
1565 | 1672 |
1566 | 1673 |
1567 void Translation::StoreLiteral(int literal_id) { | 1674 void Translation::StoreLiteral(int literal_id) { |
1568 buffer_->Add(LITERAL, zone()); | 1675 buffer_->Add(LITERAL, zone()); |
1569 buffer_->Add(literal_id, zone()); | 1676 buffer_->Add(literal_id, zone()); |
1570 } | 1677 } |
1571 | 1678 |
1572 | 1679 |
1573 void Translation::StoreArgumentsObject() { | 1680 void Translation::StoreArgumentsObject(int args_index, int args_length) { |
1574 buffer_->Add(ARGUMENTS_OBJECT, zone()); | 1681 buffer_->Add(ARGUMENTS_OBJECT, zone()); |
1682 buffer_->Add(args_index, zone()); | |
1683 buffer_->Add(args_length, zone()); | |
1575 } | 1684 } |
1576 | 1685 |
1577 | 1686 |
1578 void Translation::MarkDuplicate() { | 1687 void Translation::MarkDuplicate() { |
1579 buffer_->Add(DUPLICATE, zone()); | 1688 buffer_->Add(DUPLICATE, zone()); |
1580 } | 1689 } |
1581 | 1690 |
1582 | 1691 |
1583 int Translation::NumberOfOperandsFor(Opcode opcode) { | 1692 int Translation::NumberOfOperandsFor(Opcode opcode) { |
1584 switch (opcode) { | 1693 switch (opcode) { |
1585 case ARGUMENTS_OBJECT: | |
1586 case DUPLICATE: | 1694 case DUPLICATE: |
1587 return 0; | 1695 return 0; |
1588 case GETTER_STUB_FRAME: | 1696 case GETTER_STUB_FRAME: |
1589 case SETTER_STUB_FRAME: | 1697 case SETTER_STUB_FRAME: |
1590 case REGISTER: | 1698 case REGISTER: |
1591 case INT32_REGISTER: | 1699 case INT32_REGISTER: |
1592 case UINT32_REGISTER: | 1700 case UINT32_REGISTER: |
1593 case DOUBLE_REGISTER: | 1701 case DOUBLE_REGISTER: |
1594 case STACK_SLOT: | 1702 case STACK_SLOT: |
1595 case INT32_STACK_SLOT: | 1703 case INT32_STACK_SLOT: |
1596 case UINT32_STACK_SLOT: | 1704 case UINT32_STACK_SLOT: |
1597 case DOUBLE_STACK_SLOT: | 1705 case DOUBLE_STACK_SLOT: |
1598 case LITERAL: | 1706 case LITERAL: |
1599 return 1; | 1707 return 1; |
1600 case BEGIN: | 1708 case BEGIN: |
1601 case ARGUMENTS_ADAPTOR_FRAME: | 1709 case ARGUMENTS_ADAPTOR_FRAME: |
1602 case CONSTRUCT_STUB_FRAME: | 1710 case CONSTRUCT_STUB_FRAME: |
1711 case ARGUMENTS_OBJECT: | |
1603 return 2; | 1712 return 2; |
1604 case JS_FRAME: | 1713 case JS_FRAME: |
1605 return 3; | 1714 return 3; |
1606 } | 1715 } |
1607 UNREACHABLE(); | 1716 UNREACHABLE(); |
1608 return -1; | 1717 return -1; |
1609 } | 1718 } |
1610 | 1719 |
1611 | 1720 |
1612 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 1721 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1855 | 1964 |
1856 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 1965 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
1857 v->VisitPointer(BitCast<Object**>(&function_)); | 1966 v->VisitPointer(BitCast<Object**>(&function_)); |
1858 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 1967 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
1859 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 1968 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
1860 } | 1969 } |
1861 | 1970 |
1862 #endif // ENABLE_DEBUGGER_SUPPORT | 1971 #endif // ENABLE_DEBUGGER_SUPPORT |
1863 | 1972 |
1864 } } // namespace v8::internal | 1973 } } // namespace v8::internal |
OLD | NEW |