OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/field-index.h" | 8 #include "src/field-index.h" |
9 #include "src/hydrogen.h" | 9 #include "src/hydrogen.h" |
10 #include "src/lithium.h" | 10 #include "src/lithium.h" |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 FieldIndex index); | 64 FieldIndex index); |
65 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, | 65 void BuildStoreNamedField(HValue* object, HValue* value, FieldIndex index, |
66 Representation representation); | 66 Representation representation); |
67 | 67 |
68 enum ArgumentClass { | 68 enum ArgumentClass { |
69 NONE, | 69 NONE, |
70 SINGLE, | 70 SINGLE, |
71 MULTIPLE | 71 MULTIPLE |
72 }; | 72 }; |
73 | 73 |
| 74 HValue* UnmappedCase(HValue* elements, HValue* key); |
| 75 |
74 HValue* BuildArrayConstructor(ElementsKind kind, | 76 HValue* BuildArrayConstructor(ElementsKind kind, |
75 AllocationSiteOverrideMode override_mode, | 77 AllocationSiteOverrideMode override_mode, |
76 ArgumentClass argument_class); | 78 ArgumentClass argument_class); |
77 HValue* BuildInternalArrayConstructor(ElementsKind kind, | 79 HValue* BuildInternalArrayConstructor(ElementsKind kind, |
78 ArgumentClass argument_class); | 80 ArgumentClass argument_class); |
79 | 81 |
80 // BuildCheckAndInstallOptimizedCode emits code to install the optimized | 82 // BuildCheckAndInstallOptimizedCode emits code to install the optimized |
81 // function found in the optimized code map at map_index in js_function, if | 83 // function found in the optimized code map at map_index in js_function, if |
82 // the function at map_index matches the given native_context. Builder is | 84 // the function at map_index matches the given native_context. Builder is |
83 // left in the "Then()" state after the install. | 85 // left in the "Then()" state after the install. |
(...skipping 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( | 595 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( |
594 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); | 596 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); |
595 return Add<HLoadNamedField>(descriptors, static_cast<HValue*>(NULL), | 597 return Add<HLoadNamedField>(descriptors, static_cast<HValue*>(NULL), |
596 value_access); | 598 value_access); |
597 } | 599 } |
598 | 600 |
599 | 601 |
600 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } | 602 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } |
601 | 603 |
602 | 604 |
| 605 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) { |
| 606 HValue* result; |
| 607 HInstruction* backing_store = Add<HLoadKeyed>( |
| 608 elements, graph()->GetConstant1(), static_cast<HValue*>(NULL), |
| 609 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 610 Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map()); |
| 611 HValue* backing_store_length = |
| 612 Add<HLoadNamedField>(backing_store, static_cast<HValue*>(NULL), |
| 613 HObjectAccess::ForFixedArrayLength()); |
| 614 IfBuilder in_unmapped_range(this); |
| 615 in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length, |
| 616 Token::LT); |
| 617 in_unmapped_range.Then(); |
| 618 { |
| 619 result = Add<HLoadKeyed>(backing_store, key, static_cast<HValue*>(NULL), |
| 620 FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE); |
| 621 } |
| 622 in_unmapped_range.ElseDeopt("Outside of range"); |
| 623 in_unmapped_range.End(); |
| 624 return result; |
| 625 } |
| 626 |
| 627 |
| 628 template <> |
| 629 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { |
| 630 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
| 631 HValue* key = GetParameter(LoadDescriptor::kNameIndex); |
| 632 |
| 633 // Mapped arguments are actual arguments. Unmapped arguments are values added |
| 634 // to the arguments object after it was created for the call. Mapped arguments |
| 635 // are stored in the context at indexes given by elements[key + 2]. Unmapped |
| 636 // arguments are stored as regular indexed properties in the arguments array, |
| 637 // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed |
| 638 // look at argument object construction. |
| 639 // |
| 640 // The sloppy arguments elements array has a special format: |
| 641 // |
| 642 // 0: context |
| 643 // 1: unmapped arguments array |
| 644 // 2: mapped_index0, |
| 645 // 3: mapped_index1, |
| 646 // ... |
| 647 // |
| 648 // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments). |
| 649 // If key + 2 >= elements.length then attempt to look in the unmapped |
| 650 // arguments array (given by elements[1]) and return the value at key, missing |
| 651 // to the runtime if the unmapped arguments array is not a fixed array or if |
| 652 // key >= unmapped_arguments_array.length. |
| 653 // |
| 654 // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value |
| 655 // in the unmapped arguments array, as described above. Otherwise, t is a Smi |
| 656 // index into the context array given at elements[0]. Return the value at |
| 657 // context[t]. |
| 658 |
| 659 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); |
| 660 IfBuilder positive_smi(this); |
| 661 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), |
| 662 Token::LT); |
| 663 positive_smi.ThenDeopt("key is negative"); |
| 664 positive_smi.End(); |
| 665 |
| 666 HValue* constant_two = Add<HConstant>(2); |
| 667 HValue* elements = AddLoadElements(receiver, static_cast<HValue*>(NULL)); |
| 668 HValue* elements_length = |
| 669 Add<HLoadNamedField>(elements, static_cast<HValue*>(NULL), |
| 670 HObjectAccess::ForFixedArrayLength()); |
| 671 HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two); |
| 672 IfBuilder in_range(this); |
| 673 in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT); |
| 674 in_range.Then(); |
| 675 { |
| 676 HValue* index = AddUncasted<HAdd>(key, constant_two); |
| 677 HInstruction* mapped_index = |
| 678 Add<HLoadKeyed>(elements, index, static_cast<HValue*>(NULL), |
| 679 FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE); |
| 680 |
| 681 IfBuilder is_valid(this); |
| 682 is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index, |
| 683 graph()->GetConstantHole()); |
| 684 is_valid.Then(); |
| 685 { |
| 686 // TODO(mvstanton): I'd like to assert from this point, that if the |
| 687 // mapped_index is not the hole that it is indeed, a smi. An unnecessary |
| 688 // smi check is being emitted. |
| 689 HValue* the_context = |
| 690 Add<HLoadKeyed>(elements, graph()->GetConstant0(), |
| 691 static_cast<HValue*>(NULL), FAST_ELEMENTS); |
| 692 DCHECK(Context::kHeaderSize == FixedArray::kHeaderSize); |
| 693 HValue* result = |
| 694 Add<HLoadKeyed>(the_context, mapped_index, static_cast<HValue*>(NULL), |
| 695 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 696 environment()->Push(result); |
| 697 } |
| 698 is_valid.Else(); |
| 699 { |
| 700 HValue* result = UnmappedCase(elements, key); |
| 701 environment()->Push(result); |
| 702 } |
| 703 is_valid.End(); |
| 704 } |
| 705 in_range.Else(); |
| 706 { |
| 707 HValue* result = UnmappedCase(elements, key); |
| 708 environment()->Push(result); |
| 709 } |
| 710 in_range.End(); |
| 711 |
| 712 return environment()->Pop(); |
| 713 } |
| 714 |
| 715 |
| 716 Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() { |
| 717 return DoGenerateCode(this); |
| 718 } |
| 719 |
| 720 |
603 void CodeStubGraphBuilderBase::BuildStoreNamedField( | 721 void CodeStubGraphBuilderBase::BuildStoreNamedField( |
604 HValue* object, HValue* value, FieldIndex index, | 722 HValue* object, HValue* value, FieldIndex index, |
605 Representation representation) { | 723 Representation representation) { |
606 DCHECK(!index.is_double() || representation.IsDouble()); | 724 DCHECK(!index.is_double() || representation.IsDouble()); |
607 int offset = index.offset(); | 725 int offset = index.offset(); |
608 HObjectAccess access = | 726 HObjectAccess access = |
609 index.is_inobject() | 727 index.is_inobject() |
610 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) | 728 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) |
611 : HObjectAccess::ForBackingStoreOffset(offset, representation); | 729 : HObjectAccess::ForBackingStoreOffset(offset, representation); |
612 | 730 |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 | 1203 |
1086 | 1204 |
1087 Handle<Code> ToBooleanStub::GenerateCode() { | 1205 Handle<Code> ToBooleanStub::GenerateCode() { |
1088 return DoGenerateCode(this); | 1206 return DoGenerateCode(this); |
1089 } | 1207 } |
1090 | 1208 |
1091 | 1209 |
1092 template <> | 1210 template <> |
1093 HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() { | 1211 HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() { |
1094 StoreGlobalStub* stub = casted_stub(); | 1212 StoreGlobalStub* stub = casted_stub(); |
1095 Handle<Object> hole(isolate()->heap()->the_hole_value(), isolate()); | |
1096 Handle<Object> placeholer_value(Smi::FromInt(0), isolate()); | 1213 Handle<Object> placeholer_value(Smi::FromInt(0), isolate()); |
1097 Handle<PropertyCell> placeholder_cell = | 1214 Handle<PropertyCell> placeholder_cell = |
1098 isolate()->factory()->NewPropertyCell(placeholer_value); | 1215 isolate()->factory()->NewPropertyCell(placeholer_value); |
1099 | 1216 |
1100 HParameter* value = GetParameter(StoreDescriptor::kValueIndex); | 1217 HParameter* value = GetParameter(StoreDescriptor::kValueIndex); |
1101 | 1218 |
1102 if (stub->check_global()) { | 1219 if (stub->check_global()) { |
1103 // Check that the map of the global has not changed: use a placeholder map | 1220 // Check that the map of the global has not changed: use a placeholder map |
1104 // that will be replaced later with the global object's map. | 1221 // that will be replaced later with the global object's map. |
1105 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); | 1222 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); |
(...skipping 11 matching lines...) Expand all Loading... |
1117 IfBuilder builder(this); | 1234 IfBuilder builder(this); |
1118 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); | 1235 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); |
1119 builder.Then(); | 1236 builder.Then(); |
1120 builder.ElseDeopt("Unexpected cell contents in constant global store"); | 1237 builder.ElseDeopt("Unexpected cell contents in constant global store"); |
1121 builder.End(); | 1238 builder.End(); |
1122 } else { | 1239 } else { |
1123 // Load the payload of the global parameter cell. A hole indicates that the | 1240 // Load the payload of the global parameter cell. A hole indicates that the |
1124 // property has been deleted and that the store must be handled by the | 1241 // property has been deleted and that the store must be handled by the |
1125 // runtime. | 1242 // runtime. |
1126 IfBuilder builder(this); | 1243 IfBuilder builder(this); |
1127 HValue* hole_value = Add<HConstant>(hole); | 1244 HValue* hole_value = graph()->GetConstantHole(); |
1128 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); | 1245 builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value); |
1129 builder.Then(); | 1246 builder.Then(); |
1130 builder.Deopt("Unexpected cell contents in global store"); | 1247 builder.Deopt("Unexpected cell contents in global store"); |
1131 builder.Else(); | 1248 builder.Else(); |
1132 Add<HStoreNamedField>(cell, access, value); | 1249 Add<HStoreNamedField>(cell, access, value); |
1133 builder.End(); | 1250 builder.End(); |
1134 } | 1251 } |
1135 | 1252 |
1136 return value; | 1253 return value; |
1137 } | 1254 } |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1823 | 1940 |
1824 // Probe the stub cache. | 1941 // Probe the stub cache. |
1825 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( | 1942 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( |
1826 Code::ComputeHandlerFlags(Code::LOAD_IC)); | 1943 Code::ComputeHandlerFlags(Code::LOAD_IC)); |
1827 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); | 1944 Add<HTailCallThroughMegamorphicCache>(receiver, name, flags); |
1828 | 1945 |
1829 // We never continue. | 1946 // We never continue. |
1830 return graph()->GetConstant0(); | 1947 return graph()->GetConstant0(); |
1831 } | 1948 } |
1832 } } // namespace v8::internal | 1949 } } // namespace v8::internal |
OLD | NEW |