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

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: Improved test coverage and fixed bug. 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/hydrogen.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
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 void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
637 ASSERT_NE(DEBUGGER, bailout_type_); 640 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.
638 for (int i = 0; i < deferred_heap_numbers_.length(); i++) { 654 for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
639 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; 655 HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
640 Handle<Object> num = isolate_->factory()->NewNumber(d.value()); 656 Handle<Object> num = isolate_->factory()->NewNumber(d.value());
641 if (FLAG_trace_deopt) { 657 if (FLAG_trace_deopt) {
642 PrintF("Materializing a new heap number %p [%e] in slot %p\n", 658 PrintF("Materializing a new heap number %p [%e] in slot %p\n",
643 reinterpret_cast<void*>(*num), 659 reinterpret_cast<void*>(*num),
644 d.value(), 660 d.value(),
645 d.slot_address()); 661 d.slot_address());
646 } 662 }
663 Memory::Object_at(d.slot_address()) = *num;
664 }
647 665
648 Memory::Object_at(d.slot_address()) = *num; 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 }
649 } 711 }
650 } 712 }
651 713
652 714
653 #ifdef ENABLE_DEBUGGER_SUPPORT 715 #ifdef ENABLE_DEBUGGER_SUPPORT
654 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame( 716 void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
655 Address parameters_top, 717 Address parameters_top,
656 uint32_t parameters_size, 718 uint32_t parameters_size,
657 Address expressions_top, 719 Address expressions_top,
658 uint32_t expressions_size, 720 uint32_t expressions_size,
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 output_offset); 987 output_offset);
926 literal->ShortPrint(); 988 literal->ShortPrint();
927 PrintF(" ; literal\n"); 989 PrintF(" ; literal\n");
928 } 990 }
929 intptr_t value = reinterpret_cast<intptr_t>(literal); 991 intptr_t value = reinterpret_cast<intptr_t>(literal);
930 output_[frame_index]->SetFrameSlot(output_offset, value); 992 output_[frame_index]->SetFrameSlot(output_offset, value);
931 return; 993 return;
932 } 994 }
933 995
934 case Translation::ARGUMENTS_OBJECT: { 996 case Translation::ARGUMENTS_OBJECT: {
935 // Use the arguments marker value as a sentinel and fill in the arguments 997 int args_index = iterator->Next() + 1; // Skip receiver.
936 // object after the deoptimized frame is built. 998 int args_length = iterator->Next() - 1; // Skip receiver.
937 if (FLAG_trace_deopt) { 999 if (FLAG_trace_deopt) {
938 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", 1000 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
939 output_[frame_index]->GetTop() + output_offset, 1001 output_[frame_index]->GetTop() + output_offset,
940 output_offset); 1002 output_offset);
941 isolate_->heap()->arguments_marker()->ShortPrint(); 1003 isolate_->heap()->arguments_marker()->ShortPrint();
942 PrintF(" ; arguments object\n"); 1004 PrintF(" ; arguments object\n");
943 } 1005 }
1006 // Use the arguments marker value as a sentinel and fill in the arguments
1007 // object after the deoptimized frame is built.
944 intptr_t value = reinterpret_cast<intptr_t>( 1008 intptr_t value = reinterpret_cast<intptr_t>(
945 isolate_->heap()->arguments_marker()); 1009 isolate_->heap()->arguments_marker());
1010 AddArgumentsObject(
1011 output_[frame_index]->GetTop() + output_offset, args_length);
946 output_[frame_index]->SetFrameSlot(output_offset, value); 1012 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 }
947 return; 1020 return;
948 } 1021 }
949 } 1022 }
950 } 1023 }
951 1024
952 1025
953 static bool ObjectToInt32(Object* obj, int32_t* value) { 1026 static bool ObjectToInt32(Object* obj, int32_t* value) {
954 if (obj->IsSmi()) { 1027 if (obj->IsSmi()) {
955 *value = Smi::cast(obj)->value(); 1028 *value = Smi::cast(obj)->value();
956 return true; 1029 return true;
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 1351
1279 1352
1280 Object* Deoptimizer::ComputeLiteral(int index) const { 1353 Object* Deoptimizer::ComputeLiteral(int index) const {
1281 DeoptimizationInputData* data = DeoptimizationInputData::cast( 1354 DeoptimizationInputData* data = DeoptimizationInputData::cast(
1282 optimized_code_->deoptimization_data()); 1355 optimized_code_->deoptimization_data());
1283 FixedArray* literals = data->LiteralArray(); 1356 FixedArray* literals = data->LiteralArray();
1284 return literals->get(index); 1357 return literals->get(index);
1285 } 1358 }
1286 1359
1287 1360
1288 void Deoptimizer::AddDoubleValue(intptr_t slot_address, 1361 void Deoptimizer::AddArgumentsObject(intptr_t slot_address, int argc) {
1289 double value) { 1362 ArgumentsObjectMaterializationDescriptor object_desc(
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) {
1290 HeapNumberMaterializationDescriptor value_desc( 1374 HeapNumberMaterializationDescriptor value_desc(
1291 reinterpret_cast<Address>(slot_address), value); 1375 reinterpret_cast<Address>(slot_address), value);
1292 deferred_heap_numbers_.Add(value_desc); 1376 deferred_heap_numbers_.Add(value_desc);
1293 } 1377 }
1294 1378
1295 1379
1296 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) { 1380 MemoryChunk* Deoptimizer::CreateCode(BailoutType type) {
1297 // We cannot run this if the serializer is enabled because this will 1381 // We cannot run this if the serializer is enabled because this will
1298 // cause us to emit relocation information for the external 1382 // cause us to emit relocation information for the external
1299 // references. This is fine because the deoptimizer's code section 1383 // 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()); 1647 buffer_->Add(index, zone());
1564 } 1648 }
1565 1649
1566 1650
1567 void Translation::StoreLiteral(int literal_id) { 1651 void Translation::StoreLiteral(int literal_id) {
1568 buffer_->Add(LITERAL, zone()); 1652 buffer_->Add(LITERAL, zone());
1569 buffer_->Add(literal_id, zone()); 1653 buffer_->Add(literal_id, zone());
1570 } 1654 }
1571 1655
1572 1656
1573 void Translation::StoreArgumentsObject() { 1657 void Translation::StoreArgumentsObject(int args_index, int args_length) {
1574 buffer_->Add(ARGUMENTS_OBJECT, zone()); 1658 buffer_->Add(ARGUMENTS_OBJECT, zone());
1659 buffer_->Add(args_index, zone());
1660 buffer_->Add(args_length, zone());
1575 } 1661 }
1576 1662
1577 1663
1578 void Translation::MarkDuplicate() { 1664 void Translation::MarkDuplicate() {
1579 buffer_->Add(DUPLICATE, zone()); 1665 buffer_->Add(DUPLICATE, zone());
1580 } 1666 }
1581 1667
1582 1668
1583 int Translation::NumberOfOperandsFor(Opcode opcode) { 1669 int Translation::NumberOfOperandsFor(Opcode opcode) {
1584 switch (opcode) { 1670 switch (opcode) {
1585 case ARGUMENTS_OBJECT:
1586 case DUPLICATE: 1671 case DUPLICATE:
1587 return 0; 1672 return 0;
1588 case GETTER_STUB_FRAME: 1673 case GETTER_STUB_FRAME:
1589 case SETTER_STUB_FRAME: 1674 case SETTER_STUB_FRAME:
1590 case REGISTER: 1675 case REGISTER:
1591 case INT32_REGISTER: 1676 case INT32_REGISTER:
1592 case UINT32_REGISTER: 1677 case UINT32_REGISTER:
1593 case DOUBLE_REGISTER: 1678 case DOUBLE_REGISTER:
1594 case STACK_SLOT: 1679 case STACK_SLOT:
1595 case INT32_STACK_SLOT: 1680 case INT32_STACK_SLOT:
1596 case UINT32_STACK_SLOT: 1681 case UINT32_STACK_SLOT:
1597 case DOUBLE_STACK_SLOT: 1682 case DOUBLE_STACK_SLOT:
1598 case LITERAL: 1683 case LITERAL:
1599 return 1; 1684 return 1;
1600 case BEGIN: 1685 case BEGIN:
1601 case ARGUMENTS_ADAPTOR_FRAME: 1686 case ARGUMENTS_ADAPTOR_FRAME:
1602 case CONSTRUCT_STUB_FRAME: 1687 case CONSTRUCT_STUB_FRAME:
1688 case ARGUMENTS_OBJECT:
1603 return 2; 1689 return 2;
1604 case JS_FRAME: 1690 case JS_FRAME:
1605 return 3; 1691 return 3;
1606 } 1692 }
1607 UNREACHABLE(); 1693 UNREACHABLE();
1608 return -1; 1694 return -1;
1609 } 1695 }
1610 1696
1611 1697
1612 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 1698 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 1941
1856 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { 1942 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
1857 v->VisitPointer(BitCast<Object**>(&function_)); 1943 v->VisitPointer(BitCast<Object**>(&function_));
1858 v->VisitPointers(parameters_, parameters_ + parameters_count_); 1944 v->VisitPointers(parameters_, parameters_ + parameters_count_);
1859 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); 1945 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
1860 } 1946 }
1861 1947
1862 #endif // ENABLE_DEBUGGER_SUPPORT 1948 #endif // ENABLE_DEBUGGER_SUPPORT
1863 1949
1864 } } // namespace v8::internal 1950 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/deoptimizer.h ('k') | src/hydrogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698