| 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 |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 stack_pop_count); | 203 stack_pop_count); |
| 204 FinishCurrentBlock(hreturn_instruction); | 204 FinishCurrentBlock(hreturn_instruction); |
| 205 } | 205 } |
| 206 return true; | 206 return true; |
| 207 } | 207 } |
| 208 | 208 |
| 209 | 209 |
| 210 template <class Stub> | 210 template <class Stub> |
| 211 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase { | 211 class CodeStubGraphBuilder: public CodeStubGraphBuilderBase { |
| 212 public: | 212 public: |
| 213 explicit CodeStubGraphBuilder(Isolate* isolate, Stub* stub) | 213 CodeStubGraphBuilder(Isolate* isolate, Stub* stub) |
| 214 : CodeStubGraphBuilderBase(isolate, stub) {} | 214 : CodeStubGraphBuilderBase(isolate, stub) {} |
| 215 | 215 |
| 216 protected: | 216 protected: |
| 217 virtual HValue* BuildCodeStub() { | 217 virtual HValue* BuildCodeStub() { |
| 218 if (casted_stub()->IsUninitialized()) { | 218 if (casted_stub()->IsUninitialized()) { |
| 219 return BuildCodeUninitializedStub(); | 219 return BuildCodeUninitializedStub(); |
| 220 } else { | 220 } else { |
| 221 return BuildCodeInitializedStub(); | 221 return BuildCodeInitializedStub(); |
| 222 } | 222 } |
| 223 } | 223 } |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 HObjectAccess::ForAllocationSiteOffset( | 504 HObjectAccess::ForAllocationSiteOffset( |
| 505 AllocationSite::kTransitionInfoOffset), | 505 AllocationSite::kTransitionInfoOffset), |
| 506 initial_elements_kind); | 506 initial_elements_kind); |
| 507 | 507 |
| 508 // Unlike literals, constructed arrays don't have nested sites | 508 // Unlike literals, constructed arrays don't have nested sites |
| 509 Add<HStoreNamedField>(object, | 509 Add<HStoreNamedField>(object, |
| 510 HObjectAccess::ForAllocationSiteOffset( | 510 HObjectAccess::ForAllocationSiteOffset( |
| 511 AllocationSite::kNestedSiteOffset), | 511 AllocationSite::kNestedSiteOffset), |
| 512 graph()->GetConstant0()); | 512 graph()->GetConstant0()); |
| 513 | 513 |
| 514 // Pretenuring calculation fields. |
| 515 Add<HStoreNamedField>(object, |
| 516 HObjectAccess::ForAllocationSiteOffset( |
| 517 AllocationSite::kMementoFoundCountOffset), |
| 518 graph()->GetConstant0()); |
| 519 |
| 520 Add<HStoreNamedField>(object, |
| 521 HObjectAccess::ForAllocationSiteOffset( |
| 522 AllocationSite::kMementoCreateCountOffset), |
| 523 graph()->GetConstant0()); |
| 524 |
| 525 Add<HStoreNamedField>(object, |
| 526 HObjectAccess::ForAllocationSiteOffset( |
| 527 AllocationSite::kPretenureDecisionOffset), |
| 528 graph()->GetConstant0()); |
| 529 |
| 514 // Store an empty fixed array for the code dependency. | 530 // Store an empty fixed array for the code dependency. |
| 515 HConstant* empty_fixed_array = | 531 HConstant* empty_fixed_array = |
| 516 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 532 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
| 517 HStoreNamedField* store = Add<HStoreNamedField>( | 533 HStoreNamedField* store = Add<HStoreNamedField>( |
| 518 object, | 534 object, |
| 519 HObjectAccess::ForAllocationSiteOffset( | 535 HObjectAccess::ForAllocationSiteOffset( |
| 520 AllocationSite::kDependentCodeOffset), | 536 AllocationSite::kDependentCodeOffset), |
| 521 empty_fixed_array); | 537 empty_fixed_array); |
| 522 | 538 |
| 523 // Link the object to the allocation site list | 539 // Link the object to the allocation site list |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 587 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); | 603 HObjectAccess::ForBackingStoreOffset(casted_stub()->offset(), rep); |
| 588 return AddLoadNamedField(GetParameter(0), access); | 604 return AddLoadNamedField(GetParameter(0), access); |
| 589 } | 605 } |
| 590 | 606 |
| 591 | 607 |
| 592 Handle<Code> KeyedLoadFieldStub::GenerateCode(Isolate* isolate) { | 608 Handle<Code> KeyedLoadFieldStub::GenerateCode(Isolate* isolate) { |
| 593 return DoGenerateCode(isolate, this); | 609 return DoGenerateCode(isolate, this); |
| 594 } | 610 } |
| 595 | 611 |
| 596 | 612 |
| 613 template<> |
| 614 HValue* CodeStubGraphBuilder<KeyedArrayCallStub>::BuildCodeStub() { |
| 615 int argc = casted_stub()->argc() + 1; |
| 616 info()->set_parameter_count(argc); |
| 617 |
| 618 HValue* receiver = Add<HParameter>(1); |
| 619 |
| 620 // Load the expected initial array map from the context. |
| 621 JSArrayBuilder array_builder(this, casted_stub()->elements_kind()); |
| 622 HValue* map = array_builder.EmitMapCode(); |
| 623 |
| 624 HValue* checked_receiver = Add<HCheckMapValue>(receiver, map); |
| 625 |
| 626 HValue* function = BuildUncheckedMonomorphicElementAccess( |
| 627 checked_receiver, GetParameter(0), |
| 628 NULL, true, casted_stub()->elements_kind(), |
| 629 false, NEVER_RETURN_HOLE, STANDARD_STORE); |
| 630 return Add<HCallFunction>(function, argc, TAIL_CALL); |
| 631 } |
| 632 |
| 633 |
| 634 Handle<Code> KeyedArrayCallStub::GenerateCode(Isolate* isolate) { |
| 635 return DoGenerateCode(isolate, this); |
| 636 } |
| 637 |
| 638 |
| 597 template <> | 639 template <> |
| 598 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() { | 640 HValue* CodeStubGraphBuilder<KeyedStoreFastElementStub>::BuildCodeStub() { |
| 599 BuildUncheckedMonomorphicElementAccess( | 641 BuildUncheckedMonomorphicElementAccess( |
| 600 GetParameter(0), GetParameter(1), GetParameter(2), | 642 GetParameter(0), GetParameter(1), GetParameter(2), |
| 601 casted_stub()->is_js_array(), casted_stub()->elements_kind(), | 643 casted_stub()->is_js_array(), casted_stub()->elements_kind(), |
| 602 true, NEVER_RETURN_HOLE, casted_stub()->store_mode()); | 644 true, NEVER_RETURN_HOLE, casted_stub()->store_mode()); |
| 603 | 645 |
| 604 return GetParameter(2); | 646 return GetParameter(2); |
| 605 } | 647 } |
| 606 | 648 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( | 729 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( |
| 688 JSArrayBuilder* array_builder) { | 730 JSArrayBuilder* array_builder) { |
| 689 // Smi check and range check on the input arg. | 731 // Smi check and range check on the input arg. |
| 690 HValue* constant_one = graph()->GetConstant1(); | 732 HValue* constant_one = graph()->GetConstant1(); |
| 691 HValue* constant_zero = graph()->GetConstant0(); | 733 HValue* constant_zero = graph()->GetConstant0(); |
| 692 | 734 |
| 693 HInstruction* elements = Add<HArgumentsElements>(false); | 735 HInstruction* elements = Add<HArgumentsElements>(false); |
| 694 HInstruction* argument = Add<HAccessArgumentsAt>( | 736 HInstruction* argument = Add<HAccessArgumentsAt>( |
| 695 elements, constant_one, constant_zero); | 737 elements, constant_one, constant_zero); |
| 696 | 738 |
| 697 HConstant* max_alloc_length = | 739 return BuildAllocateArrayFromLength(array_builder, argument); |
| 698 Add<HConstant>(JSObject::kInitialMaxFastElementArray); | |
| 699 const int initial_capacity = JSArray::kPreallocatedArrayElements; | |
| 700 HConstant* initial_capacity_node = Add<HConstant>(initial_capacity); | |
| 701 | |
| 702 HInstruction* checked_arg = Add<HBoundsCheck>(argument, max_alloc_length); | |
| 703 IfBuilder if_builder(this); | |
| 704 if_builder.If<HCompareNumericAndBranch>(checked_arg, constant_zero, | |
| 705 Token::EQ); | |
| 706 if_builder.Then(); | |
| 707 Push(initial_capacity_node); // capacity | |
| 708 Push(constant_zero); // length | |
| 709 if_builder.Else(); | |
| 710 Push(checked_arg); // capacity | |
| 711 Push(checked_arg); // length | |
| 712 if_builder.End(); | |
| 713 | |
| 714 // Figure out total size | |
| 715 HValue* length = Pop(); | |
| 716 HValue* capacity = Pop(); | |
| 717 return array_builder->AllocateArray(capacity, length, true); | |
| 718 } | 740 } |
| 719 | 741 |
| 720 | 742 |
| 721 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor( | 743 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor( |
| 722 JSArrayBuilder* array_builder, ElementsKind kind) { | 744 JSArrayBuilder* array_builder, ElementsKind kind) { |
| 723 // We need to fill with the hole if it's a smi array in the multi-argument | 745 // We need to fill with the hole if it's a smi array in the multi-argument |
| 724 // case because we might have to bail out while copying arguments into | 746 // case because we might have to bail out while copying arguments into |
| 725 // the array because they aren't compatible with a smi array. | 747 // the array because they aren't compatible with a smi array. |
| 726 // If it's a double array, no problem, and if it's fast then no | 748 // If it's a double array, no problem, and if it's fast then no |
| 727 // problem either because doubles are boxed. | 749 // problem either because doubles are boxed. |
| 750 // |
| 751 // TODO(mvstanton): consider an instruction to memset fill the array |
| 752 // with zero in this case instead. |
| 728 HValue* length = GetArgumentsLength(); | 753 HValue* length = GetArgumentsLength(); |
| 729 bool fill_with_hole = IsFastSmiElementsKind(kind); | 754 JSArrayBuilder::FillMode fill_mode = IsFastSmiElementsKind(kind) |
| 755 ? JSArrayBuilder::FILL_WITH_HOLE |
| 756 : JSArrayBuilder::DONT_FILL_WITH_HOLE; |
| 730 HValue* new_object = array_builder->AllocateArray(length, | 757 HValue* new_object = array_builder->AllocateArray(length, |
| 731 length, | 758 length, |
| 732 fill_with_hole); | 759 fill_mode); |
| 733 HValue* elements = array_builder->GetElementsLocation(); | 760 HValue* elements = array_builder->GetElementsLocation(); |
| 734 ASSERT(elements != NULL); | 761 ASSERT(elements != NULL); |
| 735 | 762 |
| 736 // Now populate the elements correctly. | 763 // Now populate the elements correctly. |
| 737 LoopBuilder builder(this, | 764 LoopBuilder builder(this, |
| 738 context(), | 765 context(), |
| 739 LoopBuilder::kPostIncrement); | 766 LoopBuilder::kPostIncrement); |
| 740 HValue* start = graph()->GetConstant0(); | 767 HValue* start = graph()->GetConstant0(); |
| 741 HValue* key = builder.BeginBody(start, length, Token::LT); | 768 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 742 HInstruction* argument_elements = Add<HArgumentsElements>(false); | 769 HInstruction* argument_elements = Add<HArgumentsElements>(false); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 if (stub->operation() == Token::ADD && | 905 if (stub->operation() == Token::ADD && |
| 879 (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) && | 906 (left_type->Maybe(Type::String()) || right_type->Maybe(Type::String())) && |
| 880 !left_type->Is(Type::String()) && !right_type->Is(Type::String())) { | 907 !left_type->Is(Type::String()) && !right_type->Is(Type::String())) { |
| 881 // For the generic add stub a fast case for string addition is performance | 908 // For the generic add stub a fast case for string addition is performance |
| 882 // critical. | 909 // critical. |
| 883 if (left_type->Maybe(Type::String())) { | 910 if (left_type->Maybe(Type::String())) { |
| 884 IfBuilder if_leftisstring(this); | 911 IfBuilder if_leftisstring(this); |
| 885 if_leftisstring.If<HIsStringAndBranch>(left); | 912 if_leftisstring.If<HIsStringAndBranch>(left); |
| 886 if_leftisstring.Then(); | 913 if_leftisstring.Then(); |
| 887 { | 914 { |
| 888 Push(AddInstruction(BuildBinaryOperation( | 915 Push(BuildBinaryOperation( |
| 889 stub->operation(), left, right, | 916 stub->operation(), left, right, |
| 890 handle(Type::String(), isolate()), right_type, | 917 handle(Type::String(), isolate()), right_type, |
| 891 result_type, stub->fixed_right_arg(), true))); | 918 result_type, stub->fixed_right_arg())); |
| 892 } | 919 } |
| 893 if_leftisstring.Else(); | 920 if_leftisstring.Else(); |
| 894 { | 921 { |
| 895 Push(AddInstruction(BuildBinaryOperation( | 922 Push(BuildBinaryOperation( |
| 896 stub->operation(), left, right, | 923 stub->operation(), left, right, |
| 897 left_type, right_type, result_type, | 924 left_type, right_type, result_type, |
| 898 stub->fixed_right_arg(), true))); | 925 stub->fixed_right_arg())); |
| 899 } | 926 } |
| 900 if_leftisstring.End(); | 927 if_leftisstring.End(); |
| 901 result = Pop(); | 928 result = Pop(); |
| 902 } else { | 929 } else { |
| 903 IfBuilder if_rightisstring(this); | 930 IfBuilder if_rightisstring(this); |
| 904 if_rightisstring.If<HIsStringAndBranch>(right); | 931 if_rightisstring.If<HIsStringAndBranch>(right); |
| 905 if_rightisstring.Then(); | 932 if_rightisstring.Then(); |
| 906 { | 933 { |
| 907 Push(AddInstruction(BuildBinaryOperation( | 934 Push(BuildBinaryOperation( |
| 908 stub->operation(), left, right, | 935 stub->operation(), left, right, |
| 909 left_type, handle(Type::String(), isolate()), | 936 left_type, handle(Type::String(), isolate()), |
| 910 result_type, stub->fixed_right_arg(), true))); | 937 result_type, stub->fixed_right_arg())); |
| 911 } | 938 } |
| 912 if_rightisstring.Else(); | 939 if_rightisstring.Else(); |
| 913 { | 940 { |
| 914 Push(AddInstruction(BuildBinaryOperation( | 941 Push(BuildBinaryOperation( |
| 915 stub->operation(), left, right, | 942 stub->operation(), left, right, |
| 916 left_type, right_type, result_type, | 943 left_type, right_type, result_type, |
| 917 stub->fixed_right_arg(), true))); | 944 stub->fixed_right_arg())); |
| 918 } | 945 } |
| 919 if_rightisstring.End(); | 946 if_rightisstring.End(); |
| 920 result = Pop(); | 947 result = Pop(); |
| 921 } | 948 } |
| 922 } else { | 949 } else { |
| 923 result = AddInstruction(BuildBinaryOperation( | 950 result = BuildBinaryOperation( |
| 924 stub->operation(), left, right, | 951 stub->operation(), left, right, |
| 925 left_type, right_type, result_type, | 952 left_type, right_type, result_type, |
| 926 stub->fixed_right_arg(), true)); | 953 stub->fixed_right_arg()); |
| 927 } | 954 } |
| 928 | 955 |
| 929 // If we encounter a generic argument, the number conversion is | 956 // If we encounter a generic argument, the number conversion is |
| 930 // observable, thus we cannot afford to bail out after the fact. | 957 // observable, thus we cannot afford to bail out after the fact. |
| 931 if (!stub->HasSideEffects(isolate())) { | 958 if (!stub->HasSideEffects(isolate())) { |
| 932 if (result_type->Is(Type::Smi())) { | 959 if (result_type->Is(Type::Smi())) { |
| 933 if (stub->operation() == Token::SHR) { | 960 if (stub->operation() == Token::SHR) { |
| 934 // TODO(olivf) Replace this by a SmiTagU Instruction. | 961 // TODO(olivf) Replace this by a SmiTagU Instruction. |
| 935 // 0x40000000: this number would convert to negative when interpreting | 962 // 0x40000000: this number would convert to negative when interpreting |
| 936 // the register as signed value; | 963 // the register as signed value; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 HValue* CodeStubGraphBuilder<NewStringAddStub>::BuildCodeInitializedStub() { | 1001 HValue* CodeStubGraphBuilder<NewStringAddStub>::BuildCodeInitializedStub() { |
| 975 NewStringAddStub* stub = casted_stub(); | 1002 NewStringAddStub* stub = casted_stub(); |
| 976 StringAddFlags flags = stub->flags(); | 1003 StringAddFlags flags = stub->flags(); |
| 977 PretenureFlag pretenure_flag = stub->pretenure_flag(); | 1004 PretenureFlag pretenure_flag = stub->pretenure_flag(); |
| 978 | 1005 |
| 979 HValue* left = GetParameter(NewStringAddStub::kLeft); | 1006 HValue* left = GetParameter(NewStringAddStub::kLeft); |
| 980 HValue* right = GetParameter(NewStringAddStub::kRight); | 1007 HValue* right = GetParameter(NewStringAddStub::kRight); |
| 981 | 1008 |
| 982 // Make sure that both arguments are strings if not known in advance. | 1009 // Make sure that both arguments are strings if not known in advance. |
| 983 if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { | 1010 if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
| 984 IfBuilder if_leftnotstring(this); | 1011 left = BuildCheckString(left); |
| 985 if_leftnotstring.IfNot<HIsStringAndBranch>(left); | |
| 986 if_leftnotstring.Then(); | |
| 987 if_leftnotstring.Deopt("Expected string for LHS of string addition"); | |
| 988 } | 1012 } |
| 989 if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { | 1013 if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
| 990 IfBuilder if_rightnotstring(this); | 1014 right = BuildCheckString(right); |
| 991 if_rightnotstring.IfNot<HIsStringAndBranch>(right); | |
| 992 if_rightnotstring.Then(); | |
| 993 if_rightnotstring.Deopt("Expected string for RHS of string addition"); | |
| 994 } | 1015 } |
| 995 | 1016 |
| 996 return BuildStringAdd(left, right, pretenure_flag); | 1017 return BuildStringAdd(left, right, pretenure_flag); |
| 997 } | 1018 } |
| 998 | 1019 |
| 999 | 1020 |
| 1000 Handle<Code> NewStringAddStub::GenerateCode(Isolate* isolate) { | 1021 Handle<Code> NewStringAddStub::GenerateCode(Isolate* isolate) { |
| 1001 return DoGenerateCode(isolate, this); | 1022 return DoGenerateCode(isolate, this); |
| 1002 } | 1023 } |
| 1003 | 1024 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1285 | 1306 |
| 1286 return js_function; | 1307 return js_function; |
| 1287 } | 1308 } |
| 1288 | 1309 |
| 1289 | 1310 |
| 1290 Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) { | 1311 Handle<Code> FastNewClosureStub::GenerateCode(Isolate* isolate) { |
| 1291 return DoGenerateCode(isolate, this); | 1312 return DoGenerateCode(isolate, this); |
| 1292 } | 1313 } |
| 1293 | 1314 |
| 1294 | 1315 |
| 1316 template<> |
| 1317 HValue* CodeStubGraphBuilder<KeyedLoadDictionaryElementStub>::BuildCodeStub() { |
| 1318 HValue* receiver = GetParameter(0); |
| 1319 HValue* key = GetParameter(1); |
| 1320 |
| 1321 Add<HCheckSmi>(key); |
| 1322 |
| 1323 return BuildUncheckedDictionaryElementLoad(receiver, key); |
| 1324 } |
| 1325 |
| 1326 |
| 1327 Handle<Code> KeyedLoadDictionaryElementStub::GenerateCode(Isolate* isolate) { |
| 1328 return DoGenerateCode(isolate, this); |
| 1329 } |
| 1330 |
| 1331 |
| 1295 } } // namespace v8::internal | 1332 } } // namespace v8::internal |
| OLD | NEW |