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

Side by Side Diff: src/deoptimizer.cc

Issue 10908194: Fix arguments object materialization during deopt. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Ported to other architectures. 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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698