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" | |
31 #include "codegen.h" | 30 #include "codegen.h" |
32 #include "deoptimizer.h" | 31 #include "deoptimizer.h" |
33 #include "disasm.h" | 32 #include "disasm.h" |
34 #include "full-codegen.h" | 33 #include "full-codegen.h" |
35 #include "global-handles.h" | 34 #include "global-handles.h" |
36 #include "macro-assembler.h" | 35 #include "macro-assembler.h" |
37 #include "prettyprinter.h" | 36 #include "prettyprinter.h" |
38 | 37 |
39 | 38 |
40 namespace v8 { | 39 namespace v8 { |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 function_(function), | 361 function_(function), |
363 bailout_id_(bailout_id), | 362 bailout_id_(bailout_id), |
364 bailout_type_(type), | 363 bailout_type_(type), |
365 from_(from), | 364 from_(from), |
366 fp_to_sp_delta_(fp_to_sp_delta), | 365 fp_to_sp_delta_(fp_to_sp_delta), |
367 has_alignment_padding_(0), | 366 has_alignment_padding_(0), |
368 input_(NULL), | 367 input_(NULL), |
369 output_count_(0), | 368 output_count_(0), |
370 jsframe_count_(0), | 369 jsframe_count_(0), |
371 output_(NULL), | 370 output_(NULL), |
372 deferred_arguments_objects_values_(0), | |
373 deferred_arguments_objects_(0), | |
374 deferred_heap_numbers_(0) { | 371 deferred_heap_numbers_(0) { |
375 if (FLAG_trace_deopt && type != OSR) { | 372 if (FLAG_trace_deopt && type != OSR) { |
376 if (type == DEBUGGER) { | 373 if (type == DEBUGGER) { |
377 PrintF("**** DEOPT FOR DEBUGGER: "); | 374 PrintF("**** DEOPT FOR DEBUGGER: "); |
378 } else { | 375 } else { |
379 PrintF("**** DEOPT: "); | 376 PrintF("**** DEOPT: "); |
380 } | 377 } |
381 function->PrintName(); | 378 function->PrintName(); |
382 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", | 379 PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", |
383 bailout_id, | 380 bailout_id, |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
629 output_[index]->GetPc(), | 626 output_[index]->GetPc(), |
630 FullCodeGenerator::State2String( | 627 FullCodeGenerator::State2String( |
631 static_cast<FullCodeGenerator::State>( | 628 static_cast<FullCodeGenerator::State>( |
632 output_[index]->GetState()->value())), | 629 output_[index]->GetState()->value())), |
633 has_alignment_padding_ ? "with padding" : "no padding", | 630 has_alignment_padding_ ? "with padding" : "no padding", |
634 ms); | 631 ms); |
635 } | 632 } |
636 } | 633 } |
637 | 634 |
638 | 635 |
639 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) { | 636 void Deoptimizer::MaterializeHeapNumbers() { |
640 ASSERT_NE(DEBUGGER, bailout_type_); | 637 ASSERT_NE(DEBUGGER, bailout_type_); |
641 | |
642 // Handlify all argument object values before triggering any allocation. | |
643 List<Handle<Object> > values(deferred_arguments_objects_values_.length()); | |
644 for (int i = 0; i < deferred_arguments_objects_values_.length(); ++i) { | |
645 values.Add(Handle<Object>(deferred_arguments_objects_values_[i])); | |
646 } | |
647 | |
648 // Play it safe and clear all unhandlified values before we continue. | |
649 deferred_arguments_objects_values_.Clear(); | |
650 | |
651 // Materialize all heap numbers before looking at arguments because when the | |
652 // output frames are used to materialize arguments objects later on they need | |
653 // to already contain valid heap numbers. | |
654 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { | 638 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { |
655 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; | 639 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; |
656 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); | 640 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); |
657 if (FLAG_trace_deopt) { | 641 if (FLAG_trace_deopt) { |
658 PrintF("Materializing a new heap number %p [%e] in slot %p\n", | 642 PrintF("Materializing a new heap number %p [%e] in slot %p\n", |
659 reinterpret_cast<void*>(*num), | 643 reinterpret_cast<void*>(*num), |
660 d.value(), | 644 d.value(), |
661 d.slot_address()); | 645 d.slot_address()); |
662 } | 646 } |
| 647 |
663 Memory::Object_at(d.slot_address()) = *num; | 648 Memory::Object_at(d.slot_address()) = *num; |
664 } | 649 } |
665 | |
666 // Materialize arguments objects one frame at a time. | |
667 for (int frame_index = 0; frame_index < jsframe_count(); ++frame_index) { | |
668 if (frame_index != 0) it->Advance(); | |
669 JavaScriptFrame* frame = it->frame(); | |
670 Handle<JSFunction> function(JSFunction::cast(frame->function()), isolate_); | |
671 Handle<JSObject> arguments; | |
672 for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) { | |
673 if (frame->GetExpression(i) == isolate_->heap()->arguments_marker()) { | |
674 ArgumentsObjectMaterializationDescriptor descriptor = | |
675 deferred_arguments_objects_.RemoveLast(); | |
676 const int length = descriptor.arguments_length(); | |
677 if (arguments.is_null()) { | |
678 if (frame->has_adapted_arguments()) { | |
679 // Use the arguments adapter frame we just built to materialize the | |
680 // arguments object. FunctionGetArguments can't throw an exception, | |
681 // so cast away the doubt with an assert. | |
682 arguments = Handle<JSObject>(JSObject::cast( | |
683 Accessors::FunctionGetArguments(*function, | |
684 NULL)->ToObjectUnchecked())); | |
685 values.RewindBy(length); | |
686 } else { | |
687 // Construct an arguments object and copy the parameters to a newly | |
688 // allocated arguments object backing store. | |
689 arguments = | |
690 isolate_->factory()->NewArgumentsObject(function, length); | |
691 Handle<FixedArray> array = | |
692 isolate_->factory()->NewFixedArray(length); | |
693 ASSERT(array->length() == length); | |
694 for (int i = length - 1; i >= 0 ; --i) { | |
695 array->set(i, *values.RemoveLast()); | |
696 } | |
697 arguments->set_elements(*array); | |
698 } | |
699 } | |
700 frame->SetExpression(i, *arguments); | |
701 ASSERT_EQ(Memory::Object_at(descriptor.slot_address()), *arguments); | |
702 if (FLAG_trace_deopt) { | |
703 PrintF("Materializing %sarguments object for %p: ", | |
704 frame->has_adapted_arguments() ? "(adapted) " : "", | |
705 reinterpret_cast<void*>(descriptor.slot_address())); | |
706 arguments->ShortPrint(); | |
707 PrintF("\n"); | |
708 } | |
709 } | |
710 } | |
711 } | |
712 } | 650 } |
713 | 651 |
714 | 652 |
715 #ifdef ENABLE_DEBUGGER_SUPPORT | 653 #ifdef ENABLE_DEBUGGER_SUPPORT |
716 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( | 654 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( |
717 Address parameters_top, | 655 Address parameters_top, |
718 uint32_t parameters_size, | 656 uint32_t parameters_size, |
719 Address expressions_top, | 657 Address expressions_top, |
720 uint32_t expressions_size, | 658 uint32_t expressions_size, |
721 DeoptimizedFrameInfo* info) { | 659 DeoptimizedFrameInfo* info) { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 output_offset); | 925 output_offset); |
988 literal->ShortPrint(); | 926 literal->ShortPrint(); |
989 PrintF(" ; literal\n"); | 927 PrintF(" ; literal\n"); |
990 } | 928 } |
991 intptr_t value = reinterpret_cast<intptr_t>(literal); | 929 intptr_t value = reinterpret_cast<intptr_t>(literal); |
992 output_[frame_index]->SetFrameSlot(output_offset, value); | 930 output_[frame_index]->SetFrameSlot(output_offset, value); |
993 return; | 931 return; |
994 } | 932 } |
995 | 933 |
996 case Translation::ARGUMENTS_OBJECT: { | 934 case Translation::ARGUMENTS_OBJECT: { |
997 int args_index = iterator->Next() + 1; // Skip receiver. | 935 // Use the arguments marker value as a sentinel and fill in the arguments |
998 int args_length = iterator->Next() - 1; // Skip receiver. | 936 // object after the deoptimized frame is built. |
999 if (FLAG_trace_deopt) { | 937 if (FLAG_trace_deopt) { |
1000 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", | 938 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", |
1001 output_[frame_index]->GetTop() + output_offset, | 939 output_[frame_index]->GetTop() + output_offset, |
1002 output_offset); | 940 output_offset); |
1003 isolate_->heap()->arguments_marker()->ShortPrint(); | 941 isolate_->heap()->arguments_marker()->ShortPrint(); |
1004 PrintF(" ; arguments object\n"); | 942 PrintF(" ; arguments object\n"); |
1005 } | 943 } |
1006 // Use the arguments marker value as a sentinel and fill in the arguments | |
1007 // object after the deoptimized frame is built. | |
1008 intptr_t value = reinterpret_cast<intptr_t>( | 944 intptr_t value = reinterpret_cast<intptr_t>( |
1009 isolate_->heap()->arguments_marker()); | 945 isolate_->heap()->arguments_marker()); |
1010 AddArgumentsObject( | |
1011 output_[frame_index]->GetTop() + output_offset, args_length); | |
1012 output_[frame_index]->SetFrameSlot(output_offset, value); | 946 output_[frame_index]->SetFrameSlot(output_offset, value); |
1013 // We save the tagged argument values on the side and materialize the | |
1014 // actual arguments object after the deoptimized frame is built. | |
1015 for (int i = 0; i < args_length; i++) { | |
1016 unsigned input_offset = input_->GetOffsetFromSlotIndex(args_index + i); | |
1017 intptr_t input_value = input_->GetFrameSlot(input_offset); | |
1018 AddArgumentsObjectValue(input_value); | |
1019 } | |
1020 return; | 947 return; |
1021 } | 948 } |
1022 } | 949 } |
1023 } | 950 } |
1024 | 951 |
1025 | 952 |
1026 static bool ObjectToInt32(Object* obj, int32_t* value) { | 953 static bool ObjectToInt32(Object* obj, int32_t* value) { |
1027 if (obj->IsSmi()) { | 954 if (obj->IsSmi()) { |
1028 *value = Smi::cast(obj)->value(); | 955 *value = Smi::cast(obj)->value(); |
1029 return true; | 956 return true; |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1351 | 1278 |
1352 | 1279 |
1353 Object* Deoptimizer::ComputeLiteral(int index) const { | 1280 Object* Deoptimizer::ComputeLiteral(int index) const { |
1354 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 1281 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
1355 optimized_code_->deoptimization_data()); | 1282 optimized_code_->deoptimization_data()); |
1356 FixedArray* literals = data->LiteralArray(); | 1283 FixedArray* literals = data->LiteralArray(); |
1357 return literals->get(index); | 1284 return literals->get(index); |
1358 } | 1285 } |
1359 | 1286 |
1360 | 1287 |
1361 void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) { | 1288 void Deoptimizer::AddDoubleValue(intptr_t slot_address, |
1362 ArgumentsObjectMaterializationDescriptor object_desc( | 1289 double value) { |
1363 reinterpret_cast<Address>(slot_address), argc); | |
1364 deferred_arguments_objects_.Add(object_desc); | |
1365 } | |
1366 | |
1367 | |
1368 void Deoptimizer::AddArgumentsObjectValue(intptr_t value) { | |
1369 deferred_arguments_objects_values_.Add(reinterpret_cast<Object*>(value)); | |
1370 } | |
1371 | |
1372 | |
1373 void Deoptimizer::AddDoubleValue(intptr_t slot_address, double value) { | |
1374 HeapNumberMaterializationDescriptor value_desc( | 1290 HeapNumberMaterializationDescriptor value_desc( |
1375 reinterpret_cast<Address>(slot_address), value); | 1291 reinterpret_cast<Address>(slot_address), value); |
1376 deferred_heap_numbers_.Add(value_desc); | 1292 deferred_heap_numbers_.Add(value_desc); |
1377 } | 1293 } |
1378 | 1294 |
1379 | 1295 |
1380 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { | 1296 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { |
1381 // We cannot run this if the serializer is enabled because this will | 1297 // We cannot run this if the serializer is enabled because this will |
1382 // cause us to emit relocation information for the external | 1298 // cause us to emit relocation information for the external |
1383 // references. This is fine because the deoptimizer's code section | 1299 // references. This is fine because the deoptimizer's code section |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1647 buffer_->Add(index, zone()); | 1563 buffer_->Add(index, zone()); |
1648 } | 1564 } |
1649 | 1565 |
1650 | 1566 |
1651 void Translation::StoreLiteral(int literal_id) { | 1567 void Translation::StoreLiteral(int literal_id) { |
1652 buffer_->Add(LITERAL, zone()); | 1568 buffer_->Add(LITERAL, zone()); |
1653 buffer_->Add(literal_id, zone()); | 1569 buffer_->Add(literal_id, zone()); |
1654 } | 1570 } |
1655 | 1571 |
1656 | 1572 |
1657 void Translation::StoreArgumentsObject(int args_index, int args_length) { | 1573 void Translation::StoreArgumentsObject() { |
1658 buffer_->Add(ARGUMENTS_OBJECT, zone()); | 1574 buffer_->Add(ARGUMENTS_OBJECT, zone()); |
1659 buffer_->Add(args_index, zone()); | |
1660 buffer_->Add(args_length, zone()); | |
1661 } | 1575 } |
1662 | 1576 |
1663 | 1577 |
1664 void Translation::MarkDuplicate() { | 1578 void Translation::MarkDuplicate() { |
1665 buffer_->Add(DUPLICATE, zone()); | 1579 buffer_->Add(DUPLICATE, zone()); |
1666 } | 1580 } |
1667 | 1581 |
1668 | 1582 |
1669 int Translation::NumberOfOperandsFor(Opcode opcode) { | 1583 int Translation::NumberOfOperandsFor(Opcode opcode) { |
1670 switch (opcode) { | 1584 switch (opcode) { |
| 1585 case ARGUMENTS_OBJECT: |
1671 case DUPLICATE: | 1586 case DUPLICATE: |
1672 return 0; | 1587 return 0; |
1673 case GETTER_STUB_FRAME: | 1588 case GETTER_STUB_FRAME: |
1674 case SETTER_STUB_FRAME: | 1589 case SETTER_STUB_FRAME: |
1675 case REGISTER: | 1590 case REGISTER: |
1676 case INT32_REGISTER: | 1591 case INT32_REGISTER: |
1677 case UINT32_REGISTER: | 1592 case UINT32_REGISTER: |
1678 case DOUBLE_REGISTER: | 1593 case DOUBLE_REGISTER: |
1679 case STACK_SLOT: | 1594 case STACK_SLOT: |
1680 case INT32_STACK_SLOT: | 1595 case INT32_STACK_SLOT: |
1681 case UINT32_STACK_SLOT: | 1596 case UINT32_STACK_SLOT: |
1682 case DOUBLE_STACK_SLOT: | 1597 case DOUBLE_STACK_SLOT: |
1683 case LITERAL: | 1598 case LITERAL: |
1684 return 1; | 1599 return 1; |
1685 case BEGIN: | 1600 case BEGIN: |
1686 case ARGUMENTS_ADAPTOR_FRAME: | 1601 case ARGUMENTS_ADAPTOR_FRAME: |
1687 case CONSTRUCT_STUB_FRAME: | 1602 case CONSTRUCT_STUB_FRAME: |
1688 case ARGUMENTS_OBJECT: | |
1689 return 2; | 1603 return 2; |
1690 case JS_FRAME: | 1604 case JS_FRAME: |
1691 return 3; | 1605 return 3; |
1692 } | 1606 } |
1693 UNREACHABLE(); | 1607 UNREACHABLE(); |
1694 return -1; | 1608 return -1; |
1695 } | 1609 } |
1696 | 1610 |
1697 | 1611 |
1698 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) | 1612 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1941 | 1855 |
1942 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { | 1856 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { |
1943 v->VisitPointer(BitCast<Object**>(&function_)); | 1857 v->VisitPointer(BitCast<Object**>(&function_)); |
1944 v->VisitPointers(parameters_, parameters_ + parameters_count_); | 1858 v->VisitPointers(parameters_, parameters_ + parameters_count_); |
1945 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); | 1859 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); |
1946 } | 1860 } |
1947 | 1861 |
1948 #endif // ENABLE_DEBUGGER_SUPPORT | 1862 #endif // ENABLE_DEBUGGER_SUPPORT |
1949 | 1863 |
1950 } } // namespace v8::internal | 1864 } } // namespace v8::internal |
OLD | NEW |