| 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 |