OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/compiler/js-create-lowering.h" | 5 #include "src/compiler/js-create-lowering.h" |
6 | 6 |
| 7 #include "src/allocation-site-scopes.h" |
7 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
8 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
9 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
10 #include "src/compiler/common-operator.h" | 11 #include "src/compiler/common-operator.h" |
11 #include "src/compiler/js-graph.h" | 12 #include "src/compiler/js-graph.h" |
12 #include "src/compiler/js-operator.h" | 13 #include "src/compiler/js-operator.h" |
13 #include "src/compiler/linkage.h" | 14 #include "src/compiler/linkage.h" |
14 #include "src/compiler/node.h" | 15 #include "src/compiler/node.h" |
15 #include "src/compiler/node-properties.h" | 16 #include "src/compiler/node-properties.h" |
| 17 #include "src/compiler/operator-properties.h" |
16 #include "src/compiler/simplified-operator.h" | 18 #include "src/compiler/simplified-operator.h" |
17 #include "src/compiler/state-values-utils.h" | 19 #include "src/compiler/state-values-utils.h" |
18 | 20 |
19 namespace v8 { | 21 namespace v8 { |
20 namespace internal { | 22 namespace internal { |
21 namespace compiler { | 23 namespace compiler { |
22 | 24 |
23 namespace { | 25 namespace { |
24 | 26 |
25 // A helper class to construct inline allocations on the simplified operator | 27 // A helper class to construct inline allocations on the simplified operator |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 } | 122 } |
121 | 123 |
122 // When initializing arrays, we'll unfold the loop if the number of | 124 // When initializing arrays, we'll unfold the loop if the number of |
123 // elements is known to be of this type. | 125 // elements is known to be of this type. |
124 const int kElementLoopUnrollLimit = 16; | 126 const int kElementLoopUnrollLimit = 16; |
125 | 127 |
126 // Limits up to which context allocations are inlined. | 128 // Limits up to which context allocations are inlined. |
127 const int kFunctionContextAllocationLimit = 16; | 129 const int kFunctionContextAllocationLimit = 16; |
128 const int kBlockContextAllocationLimit = 16; | 130 const int kBlockContextAllocationLimit = 16; |
129 | 131 |
| 132 // Determines whether the given array or object literal boilerplate satisfies |
| 133 // all limits to be considered for fast deep-copying and computes the total |
| 134 // size of all objects that are part of the graph. |
| 135 bool IsFastLiteral(Handle<JSObject> boilerplate, int max_depth, |
| 136 int* max_properties) { |
| 137 DCHECK_GE(max_depth, 0); |
| 138 DCHECK_GE(*max_properties, 0); |
| 139 |
| 140 // Make sure the boilerplate map is not deprecated. |
| 141 if (!JSObject::TryMigrateInstance(boilerplate)) return false; |
| 142 |
| 143 // Check for too deep nesting. |
| 144 if (max_depth == 0) return false; |
| 145 |
| 146 // Check the elements. |
| 147 Isolate* const isolate = boilerplate->GetIsolate(); |
| 148 Handle<FixedArrayBase> elements(boilerplate->elements(), isolate); |
| 149 if (elements->length() > 0 && |
| 150 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
| 151 if (boilerplate->HasFastSmiOrObjectElements()) { |
| 152 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 153 int length = elements->length(); |
| 154 for (int i = 0; i < length; i++) { |
| 155 if ((*max_properties)-- == 0) return false; |
| 156 Handle<Object> value(fast_elements->get(i), isolate); |
| 157 if (value->IsJSObject()) { |
| 158 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 159 if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) { |
| 160 return false; |
| 161 } |
| 162 } |
| 163 } |
| 164 } else if (!boilerplate->HasFastDoubleElements()) { |
| 165 return false; |
| 166 } |
| 167 } |
| 168 |
| 169 // TODO(turbofan): Do we want to support out-of-object properties? |
| 170 Handle<FixedArray> properties(boilerplate->properties(), isolate); |
| 171 if (properties->length() > 0) return false; |
| 172 |
| 173 // Check the in-object properties. |
| 174 Handle<DescriptorArray> descriptors( |
| 175 boilerplate->map()->instance_descriptors(), isolate); |
| 176 int limit = boilerplate->map()->NumberOfOwnDescriptors(); |
| 177 for (int i = 0; i < limit; i++) { |
| 178 PropertyDetails details = descriptors->GetDetails(i); |
| 179 if (details.type() != DATA) continue; |
| 180 if ((*max_properties)-- == 0) return false; |
| 181 FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i); |
| 182 if (boilerplate->IsUnboxedDoubleField(field_index)) continue; |
| 183 Handle<Object> value(boilerplate->RawFastPropertyAt(field_index), isolate); |
| 184 if (value->IsJSObject()) { |
| 185 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 186 if (!IsFastLiteral(value_object, max_depth - 1, max_properties)) { |
| 187 return false; |
| 188 } |
| 189 } |
| 190 } |
| 191 return true; |
| 192 } |
| 193 |
| 194 // Maximum depth and total number of elements and properties for literal |
| 195 // graphs to be considered for fast deep-copying. |
| 196 const int kMaxFastLiteralDepth = 3; |
| 197 const int kMaxFastLiteralProperties = 8; |
| 198 |
130 } // namespace | 199 } // namespace |
131 | 200 |
132 Reduction JSCreateLowering::Reduce(Node* node) { | 201 Reduction JSCreateLowering::Reduce(Node* node) { |
133 switch (node->opcode()) { | 202 switch (node->opcode()) { |
134 case IrOpcode::kJSCreate: | 203 case IrOpcode::kJSCreate: |
135 return ReduceJSCreate(node); | 204 return ReduceJSCreate(node); |
136 case IrOpcode::kJSCreateArguments: | 205 case IrOpcode::kJSCreateArguments: |
137 return ReduceJSCreateArguments(node); | 206 return ReduceJSCreateArguments(node); |
138 case IrOpcode::kJSCreateArray: | 207 case IrOpcode::kJSCreateArray: |
139 return ReduceJSCreateArray(node); | 208 return ReduceJSCreateArray(node); |
140 case IrOpcode::kJSCreateIterResultObject: | 209 case IrOpcode::kJSCreateIterResultObject: |
141 return ReduceJSCreateIterResultObject(node); | 210 return ReduceJSCreateIterResultObject(node); |
| 211 case IrOpcode::kJSCreateLiteralArray: |
| 212 case IrOpcode::kJSCreateLiteralObject: |
| 213 return ReduceJSCreateLiteral(node); |
142 case IrOpcode::kJSCreateFunctionContext: | 214 case IrOpcode::kJSCreateFunctionContext: |
143 return ReduceJSCreateFunctionContext(node); | 215 return ReduceJSCreateFunctionContext(node); |
144 case IrOpcode::kJSCreateWithContext: | 216 case IrOpcode::kJSCreateWithContext: |
145 return ReduceJSCreateWithContext(node); | 217 return ReduceJSCreateWithContext(node); |
146 case IrOpcode::kJSCreateCatchContext: | 218 case IrOpcode::kJSCreateCatchContext: |
147 return ReduceJSCreateCatchContext(node); | 219 return ReduceJSCreateCatchContext(node); |
148 case IrOpcode::kJSCreateBlockContext: | 220 case IrOpcode::kJSCreateBlockContext: |
149 return ReduceJSCreateBlockContext(node); | 221 return ReduceJSCreateBlockContext(node); |
150 default: | 222 default: |
151 break; | 223 break; |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 jsgraph()->EmptyFixedArrayConstant()); | 569 jsgraph()->EmptyFixedArrayConstant()); |
498 a.Store(AccessBuilder::ForJSObjectElements(), | 570 a.Store(AccessBuilder::ForJSObjectElements(), |
499 jsgraph()->EmptyFixedArrayConstant()); | 571 jsgraph()->EmptyFixedArrayConstant()); |
500 a.Store(AccessBuilder::ForJSIteratorResultValue(), value); | 572 a.Store(AccessBuilder::ForJSIteratorResultValue(), value); |
501 a.Store(AccessBuilder::ForJSIteratorResultDone(), done); | 573 a.Store(AccessBuilder::ForJSIteratorResultDone(), done); |
502 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | 574 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); |
503 a.FinishAndChange(node); | 575 a.FinishAndChange(node); |
504 return Changed(node); | 576 return Changed(node); |
505 } | 577 } |
506 | 578 |
| 579 Reduction JSCreateLowering::ReduceJSCreateLiteral(Node* node) { |
| 580 DCHECK(node->opcode() == IrOpcode::kJSCreateLiteralArray || |
| 581 node->opcode() == IrOpcode::kJSCreateLiteralObject); |
| 582 CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op()); |
| 583 Node* effect = NodeProperties::GetEffectInput(node); |
| 584 Node* control = NodeProperties::GetControlInput(node); |
| 585 |
| 586 Handle<LiteralsArray> literals_array; |
| 587 if (GetSpecializationLiterals(node).ToHandle(&literals_array)) { |
| 588 Handle<Object> literal(literals_array->literal(p.index()), isolate()); |
| 589 if (literal->IsAllocationSite()) { |
| 590 Handle<AllocationSite> site = Handle<AllocationSite>::cast(literal); |
| 591 Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()), |
| 592 isolate()); |
| 593 int max_properties = kMaxFastLiteralProperties; |
| 594 if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) { |
| 595 AllocationSiteUsageContext site_context(isolate(), site, false); |
| 596 site_context.EnterNewScope(); |
| 597 Node* value = effect = |
| 598 AllocateFastLiteral(effect, control, boilerplate, &site_context); |
| 599 site_context.ExitScope(site, boilerplate); |
| 600 ReplaceWithValue(node, value, effect, control); |
| 601 return Replace(value); |
| 602 } |
| 603 } |
| 604 } |
| 605 |
| 606 return NoChange(); |
| 607 } |
| 608 |
507 Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) { | 609 Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) { |
508 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); | 610 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); |
509 int slot_count = OpParameter<int>(node->op()); | 611 int slot_count = OpParameter<int>(node->op()); |
510 Node* const closure = NodeProperties::GetValueInput(node, 0); | 612 Node* const closure = NodeProperties::GetValueInput(node, 0); |
511 | 613 |
512 // Use inline allocation for function contexts up to a size limit. | 614 // Use inline allocation for function contexts up to a size limit. |
513 if (slot_count < kFunctionContextAllocationLimit) { | 615 if (slot_count < kFunctionContextAllocationLimit) { |
514 // JSCreateFunctionContext[slot_count < limit]](fun) | 616 // JSCreateFunctionContext[slot_count < limit]](fun) |
515 Node* effect = NodeProperties::GetEffectInput(node); | 617 Node* effect = NodeProperties::GetEffectInput(node); |
516 Node* control = NodeProperties::GetControlInput(node); | 618 Node* control = NodeProperties::GetControlInput(node); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 // Actually allocate the backing store. | 849 // Actually allocate the backing store. |
748 AllocationBuilder a(jsgraph(), effect, control); | 850 AllocationBuilder a(jsgraph(), effect, control); |
749 a.AllocateArray(capacity, elements_map, pretenure); | 851 a.AllocateArray(capacity, elements_map, pretenure); |
750 for (int i = 0; i < capacity; ++i) { | 852 for (int i = 0; i < capacity; ++i) { |
751 Node* index = jsgraph()->Constant(i); | 853 Node* index = jsgraph()->Constant(i); |
752 a.Store(access, index, value); | 854 a.Store(access, index, value); |
753 } | 855 } |
754 return a.Finish(); | 856 return a.Finish(); |
755 } | 857 } |
756 | 858 |
| 859 Node* JSCreateLowering::AllocateFastLiteral( |
| 860 Node* effect, Node* control, Handle<JSObject> boilerplate, |
| 861 AllocationSiteUsageContext* site_context) { |
| 862 Handle<AllocationSite> current_site(*site_context->current(), isolate()); |
| 863 dependencies()->AssumeTransitionStable(current_site); |
| 864 |
| 865 PretenureFlag pretenure = NOT_TENURED; |
| 866 if (FLAG_allocation_site_pretenuring) { |
| 867 Handle<AllocationSite> top_site(*site_context->top(), isolate()); |
| 868 pretenure = top_site->GetPretenureMode(); |
| 869 if (current_site.is_identical_to(top_site)) { |
| 870 // We install a dependency for pretenuring only on the outermost literal. |
| 871 dependencies()->AssumeTenuringDecision(top_site); |
| 872 } |
| 873 } |
| 874 |
| 875 // Setup the properties backing store. |
| 876 Node* properties = jsgraph()->EmptyFixedArrayConstant(); |
| 877 |
| 878 // Setup the elements backing store. |
| 879 Node* elements = AllocateFastLiteralElements(effect, control, boilerplate, |
| 880 pretenure, site_context); |
| 881 if (elements->op()->EffectOutputCount() > 0) effect = elements; |
| 882 |
| 883 // Compute the in-object properties to store first (might have effects). |
| 884 Handle<Map> boilerplate_map(boilerplate->map(), isolate()); |
| 885 ZoneVector<std::pair<FieldAccess, Node*>> inobject_fields(zone()); |
| 886 inobject_fields.reserve(boilerplate_map->GetInObjectProperties()); |
| 887 int const boilerplate_nof = boilerplate_map->NumberOfOwnDescriptors(); |
| 888 for (int i = 0; i < boilerplate_nof; ++i) { |
| 889 PropertyDetails const property_details = |
| 890 boilerplate_map->instance_descriptors()->GetDetails(i); |
| 891 if (property_details.type() != DATA) continue; |
| 892 Handle<Name> property_name( |
| 893 boilerplate_map->instance_descriptors()->GetKey(i), isolate()); |
| 894 FieldIndex index = FieldIndex::ForDescriptor(*boilerplate_map, i); |
| 895 FieldAccess access = {kTaggedBase, index.offset(), property_name, |
| 896 Type::Tagged(), MachineType::AnyTagged()}; |
| 897 Node* value; |
| 898 if (boilerplate->IsUnboxedDoubleField(index)) { |
| 899 access.machine_type = MachineType::Float64(); |
| 900 access.type = Type::Number(); |
| 901 value = jsgraph()->Constant(boilerplate->RawFastDoublePropertyAt(index)); |
| 902 } else { |
| 903 Handle<Object> boilerplate_value(boilerplate->RawFastPropertyAt(index), |
| 904 isolate()); |
| 905 if (boilerplate_value->IsJSObject()) { |
| 906 Handle<JSObject> boilerplate_object = |
| 907 Handle<JSObject>::cast(boilerplate_value); |
| 908 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 909 value = effect = AllocateFastLiteral(effect, control, |
| 910 boilerplate_object, site_context); |
| 911 site_context->ExitScope(current_site, boilerplate_object); |
| 912 } else if (property_details.representation().IsDouble()) { |
| 913 // Allocate a mutable HeapNumber box and store the value into it. |
| 914 value = effect = AllocateMutableHeapNumber( |
| 915 Handle<HeapNumber>::cast(boilerplate_value)->value(), |
| 916 effect, control); |
| 917 } else if (property_details.representation().IsSmi()) { |
| 918 // Ensure that value is stored as smi. |
| 919 value = boilerplate_value->IsUninitialized() |
| 920 ? jsgraph()->ZeroConstant() |
| 921 : jsgraph()->Constant(boilerplate_value); |
| 922 } else { |
| 923 value = jsgraph()->Constant(boilerplate_value); |
| 924 } |
| 925 } |
| 926 inobject_fields.push_back(std::make_pair(access, value)); |
| 927 } |
| 928 |
| 929 // Fill slack at the end of the boilerplate object with filler maps. |
| 930 int const boilerplate_length = boilerplate_map->GetInObjectProperties(); |
| 931 for (int index = static_cast<int>(inobject_fields.size()); |
| 932 index < boilerplate_length; ++index) { |
| 933 FieldAccess access = |
| 934 AccessBuilder::ForJSObjectInObjectProperty(boilerplate_map, index); |
| 935 Node* value = jsgraph()->HeapConstant(factory()->one_pointer_filler_map()); |
| 936 inobject_fields.push_back(std::make_pair(access, value)); |
| 937 } |
| 938 |
| 939 // Actually allocate and initialize the object. |
| 940 AllocationBuilder builder(jsgraph(), effect, control); |
| 941 builder.Allocate(boilerplate_map->instance_size(), pretenure); |
| 942 builder.Store(AccessBuilder::ForMap(), boilerplate_map); |
| 943 builder.Store(AccessBuilder::ForJSObjectProperties(), properties); |
| 944 builder.Store(AccessBuilder::ForJSObjectElements(), elements); |
| 945 if (boilerplate_map->IsJSArrayMap()) { |
| 946 Handle<JSArray> boilerplate_array = Handle<JSArray>::cast(boilerplate); |
| 947 builder.Store( |
| 948 AccessBuilder::ForJSArrayLength(boilerplate_array->GetElementsKind()), |
| 949 handle(boilerplate_array->length(), isolate())); |
| 950 } |
| 951 for (auto const inobject_field : inobject_fields) { |
| 952 builder.Store(inobject_field.first, inobject_field.second); |
| 953 } |
| 954 return builder.Finish(); |
| 955 } |
| 956 |
| 957 Node* JSCreateLowering::AllocateFastLiteralElements( |
| 958 Node* effect, Node* control, Handle<JSObject> boilerplate, |
| 959 PretenureFlag pretenure, AllocationSiteUsageContext* site_context) { |
| 960 Handle<FixedArrayBase> boilerplate_elements(boilerplate->elements(), |
| 961 isolate()); |
| 962 |
| 963 // Empty or copy-on-write elements just store a constant. |
| 964 if (boilerplate_elements->length() == 0 || |
| 965 boilerplate_elements->map() == isolate()->heap()->fixed_cow_array_map()) { |
| 966 if (pretenure == TENURED && |
| 967 isolate()->heap()->InNewSpace(*boilerplate_elements)) { |
| 968 // If we would like to pretenure a fixed cow array, we must ensure that |
| 969 // the array is already in old space, otherwise we'll create too many |
| 970 // old-to-new-space pointers (overflowing the store buffer). |
| 971 boilerplate_elements = Handle<FixedArrayBase>( |
| 972 isolate()->factory()->CopyAndTenureFixedCOWArray( |
| 973 Handle<FixedArray>::cast(boilerplate_elements))); |
| 974 boilerplate->set_elements(*boilerplate_elements); |
| 975 } |
| 976 return jsgraph()->HeapConstant(boilerplate_elements); |
| 977 } |
| 978 |
| 979 // Compute the elements to store first (might have effects). |
| 980 int const elements_length = boilerplate_elements->length(); |
| 981 Handle<Map> elements_map(boilerplate_elements->map(), isolate()); |
| 982 ZoneVector<Node*> elements_values(elements_length, zone()); |
| 983 if (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) { |
| 984 Handle<FixedDoubleArray> elements = |
| 985 Handle<FixedDoubleArray>::cast(boilerplate_elements); |
| 986 for (int i = 0; i < elements_length; ++i) { |
| 987 if (elements->is_the_hole(i)) { |
| 988 // TODO(turbofan): We cannot currently safely pass thru the (signaling) |
| 989 // hole NaN in C++ code, as the C++ compiler on Intel might use FPU |
| 990 // instructions/registers for doubles and therefore make the NaN quiet. |
| 991 // We should consider passing doubles in the compiler as raw int64 |
| 992 // values to prevent this. |
| 993 elements_values[i] = effect = |
| 994 graph()->NewNode(simplified()->LoadElement( |
| 995 AccessBuilder::ForFixedDoubleArrayElement()), |
| 996 jsgraph()->HeapConstant(elements), |
| 997 jsgraph()->Constant(i), effect, control); |
| 998 } else { |
| 999 elements_values[i] = jsgraph()->Constant(elements->get_scalar(i)); |
| 1000 } |
| 1001 } |
| 1002 } else { |
| 1003 Handle<FixedArray> elements = |
| 1004 Handle<FixedArray>::cast(boilerplate_elements); |
| 1005 for (int i = 0; i < elements_length; ++i) { |
| 1006 if (elements->is_the_hole(i)) { |
| 1007 elements_values[i] = jsgraph()->TheHoleConstant(); |
| 1008 } else { |
| 1009 Handle<Object> element_value(elements->get(i), isolate()); |
| 1010 if (element_value->IsJSObject()) { |
| 1011 Handle<JSObject> boilerplate_object = |
| 1012 Handle<JSObject>::cast(element_value); |
| 1013 Handle<AllocationSite> current_site = site_context->EnterNewScope(); |
| 1014 elements_values[i] = effect = AllocateFastLiteral( |
| 1015 effect, control, boilerplate_object, site_context); |
| 1016 site_context->ExitScope(current_site, boilerplate_object); |
| 1017 } else { |
| 1018 elements_values[i] = jsgraph()->Constant(element_value); |
| 1019 } |
| 1020 } |
| 1021 } |
| 1022 } |
| 1023 |
| 1024 // Allocate the backing store array and store the elements. |
| 1025 AllocationBuilder builder(jsgraph(), effect, control); |
| 1026 builder.AllocateArray(elements_length, elements_map, pretenure); |
| 1027 ElementAccess const access = |
| 1028 (elements_map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE) |
| 1029 ? AccessBuilder::ForFixedDoubleArrayElement() |
| 1030 : AccessBuilder::ForFixedArrayElement(); |
| 1031 for (int i = 0; i < elements_length; ++i) { |
| 1032 builder.Store(access, jsgraph()->Constant(i), elements_values[i]); |
| 1033 } |
| 1034 return builder.Finish(); |
| 1035 } |
| 1036 |
| 1037 Node* JSCreateLowering::AllocateMutableHeapNumber(double value, Node* effect, |
| 1038 Node* control) { |
| 1039 // TODO(turbofan): Support inline allocation of MutableHeapNumber |
| 1040 // (requires proper alignment on Allocate, and Begin/FinishRegion). |
| 1041 Callable callable = CodeFactory::AllocateMutableHeapNumber(isolate()); |
| 1042 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 1043 isolate(), jsgraph()->zone(), callable.descriptor(), 0, |
| 1044 CallDescriptor::kNoFlags, Operator::kNoThrow); |
| 1045 Node* result = effect = graph()->NewNode( |
| 1046 common()->Call(desc), jsgraph()->HeapConstant(callable.code()), |
| 1047 jsgraph()->NoContextConstant(), effect, control); |
| 1048 effect = graph()->NewNode( |
| 1049 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), result, |
| 1050 jsgraph()->Constant(value), effect, control); |
| 1051 return result; |
| 1052 } |
| 1053 |
| 1054 MaybeHandle<LiteralsArray> JSCreateLowering::GetSpecializationLiterals( |
| 1055 Node* node) { |
| 1056 Node* const closure = NodeProperties::GetValueInput(node, 0); |
| 1057 switch (closure->opcode()) { |
| 1058 case IrOpcode::kHeapConstant: { |
| 1059 Handle<HeapObject> object = OpParameter<Handle<HeapObject>>(closure); |
| 1060 return handle(Handle<JSFunction>::cast(object)->literals()); |
| 1061 } |
| 1062 case IrOpcode::kParameter: { |
| 1063 int const index = ParameterIndexOf(closure->op()); |
| 1064 // The closure is always the last parameter to a JavaScript function, and |
| 1065 // {Parameter} indices start at -1, so value outputs of {Start} look like |
| 1066 // this: closure, receiver, param0, ..., paramN, context. |
| 1067 if (index == -1) { |
| 1068 return literals_array_; |
| 1069 } |
| 1070 break; |
| 1071 } |
| 1072 default: |
| 1073 break; |
| 1074 } |
| 1075 return MaybeHandle<LiteralsArray>(); |
| 1076 } |
| 1077 |
757 Factory* JSCreateLowering::factory() const { return isolate()->factory(); } | 1078 Factory* JSCreateLowering::factory() const { return isolate()->factory(); } |
758 | 1079 |
759 Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); } | 1080 Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); } |
760 | 1081 |
761 Isolate* JSCreateLowering::isolate() const { return jsgraph()->isolate(); } | 1082 Isolate* JSCreateLowering::isolate() const { return jsgraph()->isolate(); } |
762 | 1083 |
763 JSOperatorBuilder* JSCreateLowering::javascript() const { | 1084 JSOperatorBuilder* JSCreateLowering::javascript() const { |
764 return jsgraph()->javascript(); | 1085 return jsgraph()->javascript(); |
765 } | 1086 } |
766 | 1087 |
767 CommonOperatorBuilder* JSCreateLowering::common() const { | 1088 CommonOperatorBuilder* JSCreateLowering::common() const { |
768 return jsgraph()->common(); | 1089 return jsgraph()->common(); |
769 } | 1090 } |
770 | 1091 |
771 SimplifiedOperatorBuilder* JSCreateLowering::simplified() const { | 1092 SimplifiedOperatorBuilder* JSCreateLowering::simplified() const { |
772 return jsgraph()->simplified(); | 1093 return jsgraph()->simplified(); |
773 } | 1094 } |
774 | 1095 |
775 MachineOperatorBuilder* JSCreateLowering::machine() const { | 1096 MachineOperatorBuilder* JSCreateLowering::machine() const { |
776 return jsgraph()->machine(); | 1097 return jsgraph()->machine(); |
777 } | 1098 } |
778 | 1099 |
779 } // namespace compiler | 1100 } // namespace compiler |
780 } // namespace internal | 1101 } // namespace internal |
781 } // namespace v8 | 1102 } // namespace v8 |
OLD | NEW |