OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/compilation-dependencies.h" | 6 #include "src/compilation-dependencies.h" |
7 #include "src/compiler/access-builder.h" | 7 #include "src/compiler/access-builder.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/js-typed-lowering.h" | 9 #include "src/compiler/js-typed-lowering.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
11 #include "src/compiler/node-matchers.h" | 11 #include "src/compiler/node-matchers.h" |
12 #include "src/compiler/node-properties.h" | 12 #include "src/compiler/node-properties.h" |
13 #include "src/compiler/operator-properties.h" | 13 #include "src/compiler/operator-properties.h" |
14 #include "src/compiler/state-values-utils.h" | |
15 #include "src/type-cache.h" | 14 #include "src/type-cache.h" |
16 #include "src/types.h" | 15 #include "src/types.h" |
17 | 16 |
18 namespace v8 { | 17 namespace v8 { |
19 namespace internal { | 18 namespace internal { |
20 namespace compiler { | 19 namespace compiler { |
21 | 20 |
22 namespace { | |
23 | |
24 // A helper class to construct inline allocations on the simplified operator | |
25 // level. This keeps track of the effect chain for initial stores on a newly | |
26 // allocated object and also provides helpers for commonly allocated objects. | |
27 class AllocationBuilder final { | |
28 public: | |
29 AllocationBuilder(JSGraph* jsgraph, Node* effect, Node* control) | |
30 : jsgraph_(jsgraph), | |
31 allocation_(nullptr), | |
32 effect_(effect), | |
33 control_(control) {} | |
34 | |
35 // Primitive allocation of static size. | |
36 void Allocate(int size, PretenureFlag pretenure = NOT_TENURED) { | |
37 effect_ = graph()->NewNode(common()->BeginRegion(), effect_); | |
38 allocation_ = | |
39 graph()->NewNode(simplified()->Allocate(pretenure), | |
40 jsgraph()->Constant(size), effect_, control_); | |
41 effect_ = allocation_; | |
42 } | |
43 | |
44 // Primitive store into a field. | |
45 void Store(const FieldAccess& access, Node* value) { | |
46 effect_ = graph()->NewNode(simplified()->StoreField(access), allocation_, | |
47 value, effect_, control_); | |
48 } | |
49 | |
50 // Primitive store into an element. | |
51 void Store(ElementAccess const& access, Node* index, Node* value) { | |
52 effect_ = graph()->NewNode(simplified()->StoreElement(access), allocation_, | |
53 index, value, effect_, control_); | |
54 } | |
55 | |
56 // Compound allocation of a FixedArray. | |
57 void AllocateArray(int length, Handle<Map> map, | |
58 PretenureFlag pretenure = NOT_TENURED) { | |
59 DCHECK(map->instance_type() == FIXED_ARRAY_TYPE || | |
60 map->instance_type() == FIXED_DOUBLE_ARRAY_TYPE); | |
61 int size = (map->instance_type() == FIXED_ARRAY_TYPE) | |
62 ? FixedArray::SizeFor(length) | |
63 : FixedDoubleArray::SizeFor(length); | |
64 Allocate(size, pretenure); | |
65 Store(AccessBuilder::ForMap(), map); | |
66 Store(AccessBuilder::ForFixedArrayLength(), jsgraph()->Constant(length)); | |
67 } | |
68 | |
69 // Compound store of a constant into a field. | |
70 void Store(const FieldAccess& access, Handle<Object> value) { | |
71 Store(access, jsgraph()->Constant(value)); | |
72 } | |
73 | |
74 void FinishAndChange(Node* node) { | |
75 NodeProperties::SetType(allocation_, NodeProperties::GetType(node)); | |
76 node->ReplaceInput(0, allocation_); | |
77 node->ReplaceInput(1, effect_); | |
78 node->TrimInputCount(2); | |
79 NodeProperties::ChangeOp(node, common()->FinishRegion()); | |
80 } | |
81 | |
82 Node* Finish() { | |
83 return graph()->NewNode(common()->FinishRegion(), allocation_, effect_); | |
84 } | |
85 | |
86 protected: | |
87 JSGraph* jsgraph() { return jsgraph_; } | |
88 Graph* graph() { return jsgraph_->graph(); } | |
89 CommonOperatorBuilder* common() { return jsgraph_->common(); } | |
90 SimplifiedOperatorBuilder* simplified() { return jsgraph_->simplified(); } | |
91 | |
92 private: | |
93 JSGraph* const jsgraph_; | |
94 Node* allocation_; | |
95 Node* effect_; | |
96 Node* control_; | |
97 }; | |
98 | |
99 } // namespace | |
100 | |
101 | |
102 // A helper class to simplify the process of reducing a single binop node with a | 21 // A helper class to simplify the process of reducing a single binop node with a |
103 // JSOperator. This class manages the rewriting of context, control, and effect | 22 // JSOperator. This class manages the rewriting of context, control, and effect |
104 // dependencies during lowering of a binop and contains numerous helper | 23 // dependencies during lowering of a binop and contains numerous helper |
105 // functions for matching the types of inputs to an operation. | 24 // functions for matching the types of inputs to an operation. |
106 class JSBinopReduction final { | 25 class JSBinopReduction final { |
107 public: | 26 public: |
108 JSBinopReduction(JSTypedLowering* lowering, Node* node) | 27 JSBinopReduction(JSTypedLowering* lowering, Node* node) |
109 : lowering_(lowering), node_(node) {} | 28 : lowering_(lowering), node_(node) {} |
110 | 29 |
111 void ConvertInputsToNumber(Node* frame_state) { | 30 void ConvertInputsToNumber(Node* frame_state) { |
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 receiver = | 1344 receiver = |
1426 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 1345 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
1427 rconvert, rglobal, control); | 1346 rconvert, rglobal, control); |
1428 } | 1347 } |
1429 } | 1348 } |
1430 ReplaceWithValue(node, receiver, effect, control); | 1349 ReplaceWithValue(node, receiver, effect, control); |
1431 return Changed(receiver); | 1350 return Changed(receiver); |
1432 } | 1351 } |
1433 | 1352 |
1434 | 1353 |
1435 namespace { | |
1436 | |
1437 // Maximum instance size for which allocations will be inlined. | |
1438 const int kMaxInlineInstanceSize = 64 * kPointerSize; | |
1439 | |
1440 | |
1441 // Checks whether allocation using the given constructor can be inlined. | |
1442 bool IsAllocationInlineable(Handle<JSFunction> constructor) { | |
1443 // TODO(bmeurer): Further relax restrictions on inlining, i.e. | |
1444 // instance type and maybe instance size (inobject properties | |
1445 // are limited anyways by the runtime). | |
1446 return constructor->has_initial_map() && | |
1447 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | |
1448 constructor->initial_map()->instance_size() < kMaxInlineInstanceSize; | |
1449 } | |
1450 | |
1451 } // namespace | |
1452 | |
1453 | |
1454 Reduction JSTypedLowering::ReduceJSCreate(Node* node) { | |
1455 DCHECK_EQ(IrOpcode::kJSCreate, node->opcode()); | |
1456 Node* const target = NodeProperties::GetValueInput(node, 0); | |
1457 Type* const target_type = NodeProperties::GetType(target); | |
1458 Node* const new_target = NodeProperties::GetValueInput(node, 1); | |
1459 Node* const effect = NodeProperties::GetEffectInput(node); | |
1460 // TODO(turbofan): Add support for NewTarget passed to JSCreate. | |
1461 if (target != new_target) return NoChange(); | |
1462 // Extract constructor function. | |
1463 if (target_type->IsConstant() && | |
1464 target_type->AsConstant()->Value()->IsJSFunction()) { | |
1465 Handle<JSFunction> constructor = | |
1466 Handle<JSFunction>::cast(target_type->AsConstant()->Value()); | |
1467 DCHECK(constructor->IsConstructor()); | |
1468 // Force completion of inobject slack tracking before | |
1469 // generating code to finalize the instance size. | |
1470 constructor->CompleteInobjectSlackTrackingIfActive(); | |
1471 | |
1472 // TODO(bmeurer): We fall back to the runtime in case we cannot inline | |
1473 // the allocation here, which is sort of expensive. We should think about | |
1474 // a soft fallback to some NewObjectCodeStub. | |
1475 if (IsAllocationInlineable(constructor)) { | |
1476 // Compute instance size from initial map of {constructor}. | |
1477 Handle<Map> initial_map(constructor->initial_map(), isolate()); | |
1478 int const instance_size = initial_map->instance_size(); | |
1479 | |
1480 // Add a dependency on the {initial_map} to make sure that this code is | |
1481 // deoptimized whenever the {initial_map} of the {constructor} changes. | |
1482 dependencies()->AssumeInitialMapCantChange(initial_map); | |
1483 | |
1484 // Emit code to allocate the JSObject instance for the {constructor}. | |
1485 AllocationBuilder a(jsgraph(), effect, graph()->start()); | |
1486 a.Allocate(instance_size); | |
1487 a.Store(AccessBuilder::ForMap(), initial_map); | |
1488 a.Store(AccessBuilder::ForJSObjectProperties(), | |
1489 jsgraph()->EmptyFixedArrayConstant()); | |
1490 a.Store(AccessBuilder::ForJSObjectElements(), | |
1491 jsgraph()->EmptyFixedArrayConstant()); | |
1492 for (int i = 0; i < initial_map->GetInObjectProperties(); ++i) { | |
1493 a.Store(AccessBuilder::ForJSObjectInObjectProperty(initial_map, i), | |
1494 jsgraph()->UndefinedConstant()); | |
1495 } | |
1496 a.FinishAndChange(node); | |
1497 return Changed(node); | |
1498 } | |
1499 } | |
1500 return NoChange(); | |
1501 } | |
1502 | |
1503 | |
1504 namespace { | |
1505 | |
1506 // Retrieves the frame state holding actual argument values. | |
1507 Node* GetArgumentsFrameState(Node* frame_state) { | |
1508 Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput); | |
1509 FrameStateInfo outer_state_info = OpParameter<FrameStateInfo>(outer_state); | |
1510 return outer_state_info.type() == FrameStateType::kArgumentsAdaptor | |
1511 ? outer_state | |
1512 : frame_state; | |
1513 } | |
1514 | |
1515 } // namespace | |
1516 | |
1517 | |
1518 Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) { | |
1519 DCHECK_EQ(IrOpcode::kJSCreateArguments, node->opcode()); | |
1520 CreateArgumentsType type = CreateArgumentsTypeOf(node->op()); | |
1521 Node* const frame_state = NodeProperties::GetFrameStateInput(node, 0); | |
1522 Node* const outer_state = frame_state->InputAt(kFrameStateOuterStateInput); | |
1523 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
1524 | |
1525 // Use the ArgumentsAccessStub for materializing both mapped and unmapped | |
1526 // arguments object, but only for non-inlined (i.e. outermost) frames. | |
1527 if (outer_state->opcode() != IrOpcode::kFrameState) { | |
1528 if (type != CreateArgumentsType::kRestParameter) { | |
1529 // TODO(bmeurer): Cleanup this mess at some point. | |
1530 Isolate* isolate = jsgraph()->isolate(); | |
1531 int parameter_count = state_info.parameter_count() - 1; | |
1532 int parameter_offset = parameter_count * kPointerSize; | |
1533 int offset = StandardFrameConstants::kCallerSPOffset + parameter_offset; | |
1534 Node* parameter_pointer = graph()->NewNode( | |
1535 machine()->IntAdd(), graph()->NewNode(machine()->LoadFramePointer()), | |
1536 jsgraph()->IntPtrConstant(offset)); | |
1537 Handle<SharedFunctionInfo> shared; | |
1538 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); | |
1539 bool unmapped = type == CreateArgumentsType::kUnmappedArguments; | |
1540 Callable callable = CodeFactory::ArgumentsAccess( | |
1541 isolate, unmapped, shared->has_duplicate_parameters()); | |
1542 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | |
1543 isolate, graph()->zone(), callable.descriptor(), 0, | |
1544 CallDescriptor::kNeedsFrameState); | |
1545 const Operator* new_op = common()->Call(desc); | |
1546 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | |
1547 node->InsertInput(graph()->zone(), 0, stub_code); | |
1548 node->InsertInput(graph()->zone(), 2, | |
1549 jsgraph()->Constant(parameter_count)); | |
1550 node->InsertInput(graph()->zone(), 3, parameter_pointer); | |
1551 NodeProperties::ChangeOp(node, new_op); | |
1552 return Changed(node); | |
1553 } else { | |
1554 Callable callable = CodeFactory::FastNewRestParameter(isolate()); | |
1555 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | |
1556 isolate(), graph()->zone(), callable.descriptor(), 0, | |
1557 CallDescriptor::kNeedsFrameState); | |
1558 const Operator* new_op = common()->Call(desc); | |
1559 Node* stub_code = jsgraph()->HeapConstant(callable.code()); | |
1560 node->InsertInput(graph()->zone(), 0, stub_code); | |
1561 NodeProperties::ChangeOp(node, new_op); | |
1562 return Changed(node); | |
1563 } | |
1564 } else if (outer_state->opcode() == IrOpcode::kFrameState) { | |
1565 // Use inline allocation for all mapped arguments objects within inlined | |
1566 // (i.e. non-outermost) frames, independent of the object size. | |
1567 if (type == CreateArgumentsType::kMappedArguments) { | |
1568 Handle<SharedFunctionInfo> shared; | |
1569 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); | |
1570 Node* const callee = NodeProperties::GetValueInput(node, 0); | |
1571 Node* const control = NodeProperties::GetControlInput(node); | |
1572 Node* const context = NodeProperties::GetContextInput(node); | |
1573 Node* effect = NodeProperties::GetEffectInput(node); | |
1574 // TODO(mstarzinger): Duplicate parameters are not handled yet. | |
1575 if (shared->has_duplicate_parameters()) return NoChange(); | |
1576 // Choose the correct frame state and frame state info depending on | |
1577 // whether there conceptually is an arguments adaptor frame in the call | |
1578 // chain. | |
1579 Node* const args_state = GetArgumentsFrameState(frame_state); | |
1580 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); | |
1581 // Prepare element backing store to be used by arguments object. | |
1582 bool has_aliased_arguments = false; | |
1583 Node* const elements = AllocateAliasedArguments( | |
1584 effect, control, args_state, context, shared, &has_aliased_arguments); | |
1585 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; | |
1586 // Load the arguments object map from the current native context. | |
1587 Node* const load_native_context = effect = graph()->NewNode( | |
1588 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1589 context, context, effect); | |
1590 Node* const load_arguments_map = effect = graph()->NewNode( | |
1591 simplified()->LoadField(AccessBuilder::ForContextSlot( | |
1592 has_aliased_arguments ? Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX | |
1593 : Context::SLOPPY_ARGUMENTS_MAP_INDEX)), | |
1594 load_native_context, effect, control); | |
1595 // Actually allocate and initialize the arguments object. | |
1596 AllocationBuilder a(jsgraph(), effect, control); | |
1597 Node* properties = jsgraph()->EmptyFixedArrayConstant(); | |
1598 int length = args_state_info.parameter_count() - 1; // Minus receiver. | |
1599 STATIC_ASSERT(Heap::kSloppyArgumentsObjectSize == 5 * kPointerSize); | |
1600 a.Allocate(Heap::kSloppyArgumentsObjectSize); | |
1601 a.Store(AccessBuilder::ForMap(), load_arguments_map); | |
1602 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | |
1603 a.Store(AccessBuilder::ForJSObjectElements(), elements); | |
1604 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); | |
1605 a.Store(AccessBuilder::ForArgumentsCallee(), callee); | |
1606 RelaxControls(node); | |
1607 a.FinishAndChange(node); | |
1608 return Changed(node); | |
1609 } else if (type == CreateArgumentsType::kUnmappedArguments) { | |
1610 // Use inline allocation for all unmapped arguments objects within inlined | |
1611 // (i.e. non-outermost) frames, independent of the object size. | |
1612 Node* const control = NodeProperties::GetControlInput(node); | |
1613 Node* const context = NodeProperties::GetContextInput(node); | |
1614 Node* effect = NodeProperties::GetEffectInput(node); | |
1615 // Choose the correct frame state and frame state info depending on | |
1616 // whether there conceptually is an arguments adaptor frame in the call | |
1617 // chain. | |
1618 Node* const args_state = GetArgumentsFrameState(frame_state); | |
1619 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); | |
1620 // Prepare element backing store to be used by arguments object. | |
1621 Node* const elements = AllocateArguments(effect, control, args_state); | |
1622 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; | |
1623 // Load the arguments object map from the current native context. | |
1624 Node* const load_native_context = effect = graph()->NewNode( | |
1625 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1626 context, context, effect); | |
1627 Node* const load_arguments_map = effect = graph()->NewNode( | |
1628 simplified()->LoadField(AccessBuilder::ForContextSlot( | |
1629 Context::STRICT_ARGUMENTS_MAP_INDEX)), | |
1630 load_native_context, effect, control); | |
1631 // Actually allocate and initialize the arguments object. | |
1632 AllocationBuilder a(jsgraph(), effect, control); | |
1633 Node* properties = jsgraph()->EmptyFixedArrayConstant(); | |
1634 int length = args_state_info.parameter_count() - 1; // Minus receiver. | |
1635 STATIC_ASSERT(Heap::kStrictArgumentsObjectSize == 4 * kPointerSize); | |
1636 a.Allocate(Heap::kStrictArgumentsObjectSize); | |
1637 a.Store(AccessBuilder::ForMap(), load_arguments_map); | |
1638 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | |
1639 a.Store(AccessBuilder::ForJSObjectElements(), elements); | |
1640 a.Store(AccessBuilder::ForArgumentsLength(), jsgraph()->Constant(length)); | |
1641 RelaxControls(node); | |
1642 a.FinishAndChange(node); | |
1643 return Changed(node); | |
1644 } else if (type == CreateArgumentsType::kRestParameter) { | |
1645 Handle<SharedFunctionInfo> shared; | |
1646 if (!state_info.shared_info().ToHandle(&shared)) return NoChange(); | |
1647 int start_index = shared->internal_formal_parameter_count(); | |
1648 // Use inline allocation for all unmapped arguments objects within inlined | |
1649 // (i.e. non-outermost) frames, independent of the object size. | |
1650 Node* const control = NodeProperties::GetControlInput(node); | |
1651 Node* const context = NodeProperties::GetContextInput(node); | |
1652 Node* effect = NodeProperties::GetEffectInput(node); | |
1653 // Choose the correct frame state and frame state info depending on | |
1654 // whether there conceptually is an arguments adaptor frame in the call | |
1655 // chain. | |
1656 Node* const args_state = GetArgumentsFrameState(frame_state); | |
1657 FrameStateInfo args_state_info = OpParameter<FrameStateInfo>(args_state); | |
1658 // Prepare element backing store to be used by the rest array. | |
1659 Node* const elements = | |
1660 AllocateRestArguments(effect, control, args_state, start_index); | |
1661 effect = elements->op()->EffectOutputCount() > 0 ? elements : effect; | |
1662 // Load the JSArray object map from the current native context. | |
1663 Node* const load_native_context = effect = graph()->NewNode( | |
1664 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1665 context, context, effect); | |
1666 Node* const load_jsarray_map = effect = graph()->NewNode( | |
1667 simplified()->LoadField(AccessBuilder::ForContextSlot( | |
1668 Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX)), | |
1669 load_native_context, effect, control); | |
1670 // Actually allocate and initialize the jsarray. | |
1671 AllocationBuilder a(jsgraph(), effect, control); | |
1672 Node* properties = jsgraph()->EmptyFixedArrayConstant(); | |
1673 | |
1674 // -1 to minus receiver | |
1675 int argument_count = args_state_info.parameter_count() - 1; | |
1676 int length = std::max(0, argument_count - start_index); | |
1677 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
1678 a.Allocate(JSArray::kSize); | |
1679 a.Store(AccessBuilder::ForMap(), load_jsarray_map); | |
1680 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | |
1681 a.Store(AccessBuilder::ForJSObjectElements(), elements); | |
1682 a.Store(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS), | |
1683 jsgraph()->Constant(length)); | |
1684 RelaxControls(node); | |
1685 a.FinishAndChange(node); | |
1686 return Changed(node); | |
1687 } | |
1688 } | |
1689 | |
1690 return NoChange(); | |
1691 } | |
1692 | |
1693 | |
1694 Reduction JSTypedLowering::ReduceNewArray(Node* node, Node* length, | |
1695 int capacity, | |
1696 Handle<AllocationSite> site) { | |
1697 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); | |
1698 Node* context = NodeProperties::GetContextInput(node); | |
1699 Node* effect = NodeProperties::GetEffectInput(node); | |
1700 Node* control = NodeProperties::GetControlInput(node); | |
1701 | |
1702 // Extract transition and tenuring feedback from the {site} and add | |
1703 // appropriate code dependencies on the {site} if deoptimization is | |
1704 // enabled. | |
1705 PretenureFlag pretenure = site->GetPretenureMode(); | |
1706 ElementsKind elements_kind = site->GetElementsKind(); | |
1707 DCHECK(IsFastElementsKind(elements_kind)); | |
1708 if (flags() & kDeoptimizationEnabled) { | |
1709 dependencies()->AssumeTenuringDecision(site); | |
1710 dependencies()->AssumeTransitionStable(site); | |
1711 } | |
1712 | |
1713 // Retrieve the initial map for the array from the appropriate native context. | |
1714 Node* native_context = effect = graph()->NewNode( | |
1715 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1716 context, context, effect); | |
1717 Node* js_array_map = effect = graph()->NewNode( | |
1718 javascript()->LoadContext(0, Context::ArrayMapIndex(elements_kind), true), | |
1719 native_context, native_context, effect); | |
1720 | |
1721 // Setup elements and properties. | |
1722 Node* elements; | |
1723 if (capacity == 0) { | |
1724 elements = jsgraph()->EmptyFixedArrayConstant(); | |
1725 } else { | |
1726 elements = effect = | |
1727 AllocateElements(effect, control, elements_kind, capacity, pretenure); | |
1728 } | |
1729 Node* properties = jsgraph()->EmptyFixedArrayConstant(); | |
1730 | |
1731 // Perform the allocation of the actual JSArray object. | |
1732 AllocationBuilder a(jsgraph(), effect, control); | |
1733 a.Allocate(JSArray::kSize, pretenure); | |
1734 a.Store(AccessBuilder::ForMap(), js_array_map); | |
1735 a.Store(AccessBuilder::ForJSObjectProperties(), properties); | |
1736 a.Store(AccessBuilder::ForJSObjectElements(), elements); | |
1737 a.Store(AccessBuilder::ForJSArrayLength(elements_kind), length); | |
1738 RelaxControls(node); | |
1739 a.FinishAndChange(node); | |
1740 return Changed(node); | |
1741 } | |
1742 | |
1743 | |
1744 Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) { | |
1745 DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode()); | |
1746 CreateArrayParameters const& p = CreateArrayParametersOf(node->op()); | |
1747 Node* target = NodeProperties::GetValueInput(node, 0); | |
1748 Node* new_target = NodeProperties::GetValueInput(node, 1); | |
1749 | |
1750 // TODO(bmeurer): Optimize the subclassing case. | |
1751 if (target != new_target) return NoChange(); | |
1752 | |
1753 // Check if we have a feedback {site} on the {node}. | |
1754 Handle<AllocationSite> site = p.site(); | |
1755 if (p.site().is_null()) return NoChange(); | |
1756 | |
1757 // Attempt to inline calls to the Array constructor for the relevant cases | |
1758 // where either no arguments are provided, or exactly one unsigned number | |
1759 // argument is given. | |
1760 if (site->CanInlineCall()) { | |
1761 if (p.arity() == 0) { | |
1762 Node* length = jsgraph()->ZeroConstant(); | |
1763 int capacity = JSArray::kPreallocatedArrayElements; | |
1764 return ReduceNewArray(node, length, capacity, site); | |
1765 } else if (p.arity() == 1) { | |
1766 Node* length = NodeProperties::GetValueInput(node, 2); | |
1767 Type* length_type = NodeProperties::GetType(length); | |
1768 if (length_type->Is(type_cache_.kElementLoopUnrollType)) { | |
1769 int capacity = static_cast<int>(length_type->Max()); | |
1770 return ReduceNewArray(node, length, capacity, site); | |
1771 } | |
1772 } | |
1773 } | |
1774 | |
1775 return NoChange(); | |
1776 } | |
1777 | |
1778 | |
1779 Reduction JSTypedLowering::ReduceJSCreateIterResultObject(Node* node) { | |
1780 DCHECK_EQ(IrOpcode::kJSCreateIterResultObject, node->opcode()); | |
1781 Node* value = NodeProperties::GetValueInput(node, 0); | |
1782 Node* done = NodeProperties::GetValueInput(node, 1); | |
1783 Node* context = NodeProperties::GetContextInput(node); | |
1784 Node* effect = NodeProperties::GetEffectInput(node); | |
1785 | |
1786 // Load the JSIteratorResult map for the {context}. | |
1787 Node* native_context = effect = graph()->NewNode( | |
1788 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1789 context, context, effect); | |
1790 Node* iterator_result_map = effect = graph()->NewNode( | |
1791 javascript()->LoadContext(0, Context::ITERATOR_RESULT_MAP_INDEX, true), | |
1792 native_context, native_context, effect); | |
1793 | |
1794 // Emit code to allocate the JSIteratorResult instance. | |
1795 AllocationBuilder a(jsgraph(), effect, graph()->start()); | |
1796 a.Allocate(JSIteratorResult::kSize); | |
1797 a.Store(AccessBuilder::ForMap(), iterator_result_map); | |
1798 a.Store(AccessBuilder::ForJSObjectProperties(), | |
1799 jsgraph()->EmptyFixedArrayConstant()); | |
1800 a.Store(AccessBuilder::ForJSObjectElements(), | |
1801 jsgraph()->EmptyFixedArrayConstant()); | |
1802 a.Store(AccessBuilder::ForJSIteratorResultValue(), value); | |
1803 a.Store(AccessBuilder::ForJSIteratorResultDone(), done); | |
1804 STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize); | |
1805 a.FinishAndChange(node); | |
1806 return Changed(node); | |
1807 } | |
1808 | |
1809 | |
1810 Reduction JSTypedLowering::ReduceJSCreateFunctionContext(Node* node) { | |
1811 DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode()); | |
1812 int slot_count = OpParameter<int>(node->op()); | |
1813 Node* const closure = NodeProperties::GetValueInput(node, 0); | |
1814 | |
1815 // Use inline allocation for function contexts up to a size limit. | |
1816 if (slot_count < kFunctionContextAllocationLimit) { | |
1817 // JSCreateFunctionContext[slot_count < limit]](fun) | |
1818 Node* effect = NodeProperties::GetEffectInput(node); | |
1819 Node* control = NodeProperties::GetControlInput(node); | |
1820 Node* context = NodeProperties::GetContextInput(node); | |
1821 Node* extension = jsgraph()->TheHoleConstant(); | |
1822 Node* native_context = effect = graph()->NewNode( | |
1823 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1824 context, context, effect); | |
1825 AllocationBuilder a(jsgraph(), effect, control); | |
1826 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1827 int context_length = slot_count + Context::MIN_CONTEXT_SLOTS; | |
1828 a.AllocateArray(context_length, factory()->function_context_map()); | |
1829 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1830 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1831 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); | |
1832 a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX), | |
1833 native_context); | |
1834 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | |
1835 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); | |
1836 } | |
1837 RelaxControls(node); | |
1838 a.FinishAndChange(node); | |
1839 return Changed(node); | |
1840 } | |
1841 | |
1842 return NoChange(); | |
1843 } | |
1844 | |
1845 | |
1846 Reduction JSTypedLowering::ReduceJSCreateWithContext(Node* node) { | |
1847 DCHECK_EQ(IrOpcode::kJSCreateWithContext, node->opcode()); | |
1848 Node* object = NodeProperties::GetValueInput(node, 0); | |
1849 Node* closure = NodeProperties::GetValueInput(node, 1); | |
1850 Node* effect = NodeProperties::GetEffectInput(node); | |
1851 Node* control = NodeProperties::GetControlInput(node); | |
1852 Node* context = NodeProperties::GetContextInput(node); | |
1853 Node* native_context = effect = graph()->NewNode( | |
1854 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1855 context, context, effect); | |
1856 AllocationBuilder a(jsgraph(), effect, control); | |
1857 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1858 a.AllocateArray(Context::MIN_CONTEXT_SLOTS, factory()->with_context_map()); | |
1859 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1860 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1861 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), object); | |
1862 a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX), | |
1863 native_context); | |
1864 RelaxControls(node); | |
1865 a.FinishAndChange(node); | |
1866 return Changed(node); | |
1867 } | |
1868 | |
1869 | |
1870 Reduction JSTypedLowering::ReduceJSCreateCatchContext(Node* node) { | |
1871 DCHECK_EQ(IrOpcode::kJSCreateCatchContext, node->opcode()); | |
1872 Handle<String> name = OpParameter<Handle<String>>(node); | |
1873 Node* exception = NodeProperties::GetValueInput(node, 0); | |
1874 Node* closure = NodeProperties::GetValueInput(node, 1); | |
1875 Node* effect = NodeProperties::GetEffectInput(node); | |
1876 Node* control = NodeProperties::GetControlInput(node); | |
1877 Node* context = NodeProperties::GetContextInput(node); | |
1878 Node* native_context = effect = graph()->NewNode( | |
1879 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1880 context, context, effect); | |
1881 AllocationBuilder a(jsgraph(), effect, control); | |
1882 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1883 a.AllocateArray(Context::MIN_CONTEXT_SLOTS + 1, | |
1884 factory()->catch_context_map()); | |
1885 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1886 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1887 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), name); | |
1888 a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX), | |
1889 native_context); | |
1890 a.Store(AccessBuilder::ForContextSlot(Context::THROWN_OBJECT_INDEX), | |
1891 exception); | |
1892 RelaxControls(node); | |
1893 a.FinishAndChange(node); | |
1894 return Changed(node); | |
1895 } | |
1896 | |
1897 | |
1898 Reduction JSTypedLowering::ReduceJSCreateBlockContext(Node* node) { | |
1899 DCHECK_EQ(IrOpcode::kJSCreateBlockContext, node->opcode()); | |
1900 Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node); | |
1901 int context_length = scope_info->ContextLength(); | |
1902 Node* const closure = NodeProperties::GetValueInput(node, 0); | |
1903 | |
1904 // Use inline allocation for block contexts up to a size limit. | |
1905 if (context_length < kBlockContextAllocationLimit) { | |
1906 // JSCreateBlockContext[scope[length < limit]](fun) | |
1907 Node* effect = NodeProperties::GetEffectInput(node); | |
1908 Node* control = NodeProperties::GetControlInput(node); | |
1909 Node* context = NodeProperties::GetContextInput(node); | |
1910 Node* extension = jsgraph()->Constant(scope_info); | |
1911 Node* native_context = effect = graph()->NewNode( | |
1912 javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true), | |
1913 context, context, effect); | |
1914 AllocationBuilder a(jsgraph(), effect, control); | |
1915 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == 4); // Ensure fully covered. | |
1916 a.AllocateArray(context_length, factory()->block_context_map()); | |
1917 a.Store(AccessBuilder::ForContextSlot(Context::CLOSURE_INDEX), closure); | |
1918 a.Store(AccessBuilder::ForContextSlot(Context::PREVIOUS_INDEX), context); | |
1919 a.Store(AccessBuilder::ForContextSlot(Context::EXTENSION_INDEX), extension); | |
1920 a.Store(AccessBuilder::ForContextSlot(Context::NATIVE_CONTEXT_INDEX), | |
1921 native_context); | |
1922 for (int i = Context::MIN_CONTEXT_SLOTS; i < context_length; ++i) { | |
1923 a.Store(AccessBuilder::ForContextSlot(i), jsgraph()->UndefinedConstant()); | |
1924 } | |
1925 RelaxControls(node); | |
1926 a.FinishAndChange(node); | |
1927 return Changed(node); | |
1928 } | |
1929 | |
1930 return NoChange(); | |
1931 } | |
1932 | |
1933 | |
1934 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) { | 1354 Reduction JSTypedLowering::ReduceJSCallConstruct(Node* node) { |
1935 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); | 1355 DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode()); |
1936 CallConstructParameters const& p = CallConstructParametersOf(node->op()); | 1356 CallConstructParameters const& p = CallConstructParametersOf(node->op()); |
1937 DCHECK_LE(2u, p.arity()); | 1357 DCHECK_LE(2u, p.arity()); |
1938 int const arity = static_cast<int>(p.arity() - 2); | 1358 int const arity = static_cast<int>(p.arity() - 2); |
1939 Node* target = NodeProperties::GetValueInput(node, 0); | 1359 Node* target = NodeProperties::GetValueInput(node, 0); |
1940 Type* target_type = NodeProperties::GetType(target); | 1360 Type* target_type = NodeProperties::GetType(target); |
1941 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); | 1361 Node* new_target = NodeProperties::GetValueInput(node, arity + 1); |
1942 | 1362 |
1943 // Check if {target} is a known JSFunction. | 1363 // Check if {target} is a known JSFunction. |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2306 case IrOpcode::kJSStoreProperty: | 1726 case IrOpcode::kJSStoreProperty: |
2307 return ReduceJSStoreProperty(node); | 1727 return ReduceJSStoreProperty(node); |
2308 case IrOpcode::kJSInstanceOf: | 1728 case IrOpcode::kJSInstanceOf: |
2309 return ReduceJSInstanceOf(node); | 1729 return ReduceJSInstanceOf(node); |
2310 case IrOpcode::kJSLoadContext: | 1730 case IrOpcode::kJSLoadContext: |
2311 return ReduceJSLoadContext(node); | 1731 return ReduceJSLoadContext(node); |
2312 case IrOpcode::kJSStoreContext: | 1732 case IrOpcode::kJSStoreContext: |
2313 return ReduceJSStoreContext(node); | 1733 return ReduceJSStoreContext(node); |
2314 case IrOpcode::kJSConvertReceiver: | 1734 case IrOpcode::kJSConvertReceiver: |
2315 return ReduceJSConvertReceiver(node); | 1735 return ReduceJSConvertReceiver(node); |
2316 case IrOpcode::kJSCreate: | |
2317 return ReduceJSCreate(node); | |
2318 case IrOpcode::kJSCreateArguments: | |
2319 return ReduceJSCreateArguments(node); | |
2320 case IrOpcode::kJSCreateArray: | |
2321 return ReduceJSCreateArray(node); | |
2322 case IrOpcode::kJSCreateIterResultObject: | |
2323 return ReduceJSCreateIterResultObject(node); | |
2324 case IrOpcode::kJSCreateFunctionContext: | |
2325 return ReduceJSCreateFunctionContext(node); | |
2326 case IrOpcode::kJSCreateWithContext: | |
2327 return ReduceJSCreateWithContext(node); | |
2328 case IrOpcode::kJSCreateCatchContext: | |
2329 return ReduceJSCreateCatchContext(node); | |
2330 case IrOpcode::kJSCreateBlockContext: | |
2331 return ReduceJSCreateBlockContext(node); | |
2332 case IrOpcode::kJSCallConstruct: | 1736 case IrOpcode::kJSCallConstruct: |
2333 return ReduceJSCallConstruct(node); | 1737 return ReduceJSCallConstruct(node); |
2334 case IrOpcode::kJSCallFunction: | 1738 case IrOpcode::kJSCallFunction: |
2335 return ReduceJSCallFunction(node); | 1739 return ReduceJSCallFunction(node); |
2336 case IrOpcode::kJSForInDone: | 1740 case IrOpcode::kJSForInDone: |
2337 return ReduceJSForInDone(node); | 1741 return ReduceJSForInDone(node); |
2338 case IrOpcode::kJSForInNext: | 1742 case IrOpcode::kJSForInNext: |
2339 return ReduceJSForInNext(node); | 1743 return ReduceJSForInNext(node); |
2340 case IrOpcode::kJSForInStep: | 1744 case IrOpcode::kJSForInStep: |
2341 return ReduceJSForInStep(node); | 1745 return ReduceJSForInStep(node); |
2342 case IrOpcode::kSelect: | 1746 case IrOpcode::kSelect: |
2343 return ReduceSelect(node); | 1747 return ReduceSelect(node); |
2344 default: | 1748 default: |
2345 break; | 1749 break; |
2346 } | 1750 } |
2347 return NoChange(); | 1751 return NoChange(); |
2348 } | 1752 } |
2349 | 1753 |
2350 | 1754 |
2351 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { | 1755 Node* JSTypedLowering::Word32Shl(Node* const lhs, int32_t const rhs) { |
2352 if (rhs == 0) return lhs; | 1756 if (rhs == 0) return lhs; |
2353 return graph()->NewNode(machine()->Word32Shl(), lhs, | 1757 return graph()->NewNode(machine()->Word32Shl(), lhs, |
2354 jsgraph()->Int32Constant(rhs)); | 1758 jsgraph()->Int32Constant(rhs)); |
2355 } | 1759 } |
2356 | 1760 |
2357 | 1761 |
2358 // Helper that allocates a FixedArray holding argument values recorded in the | |
2359 // given {frame_state}. Serves as backing store for JSCreateArguments nodes. | |
2360 Node* JSTypedLowering::AllocateArguments(Node* effect, Node* control, | |
2361 Node* frame_state) { | |
2362 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
2363 int argument_count = state_info.parameter_count() - 1; // Minus receiver. | |
2364 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); | |
2365 | |
2366 // Prepare an iterator over argument values recorded in the frame state. | |
2367 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); | |
2368 StateValuesAccess parameters_access(parameters); | |
2369 auto parameters_it = ++parameters_access.begin(); | |
2370 | |
2371 // Actually allocate the backing store. | |
2372 AllocationBuilder a(jsgraph(), effect, control); | |
2373 a.AllocateArray(argument_count, factory()->fixed_array_map()); | |
2374 for (int i = 0; i < argument_count; ++i, ++parameters_it) { | |
2375 a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node); | |
2376 } | |
2377 return a.Finish(); | |
2378 } | |
2379 | |
2380 | |
2381 // Helper that allocates a FixedArray holding argument values recorded in the | |
2382 // given {frame_state}. Serves as backing store for JSCreateArguments nodes. | |
2383 Node* JSTypedLowering::AllocateRestArguments(Node* effect, Node* control, | |
2384 Node* frame_state, | |
2385 int start_index) { | |
2386 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
2387 int argument_count = state_info.parameter_count() - 1; // Minus receiver. | |
2388 int num_elements = std::max(0, argument_count - start_index); | |
2389 if (num_elements == 0) return jsgraph()->EmptyFixedArrayConstant(); | |
2390 | |
2391 // Prepare an iterator over argument values recorded in the frame state. | |
2392 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); | |
2393 StateValuesAccess parameters_access(parameters); | |
2394 auto parameters_it = ++parameters_access.begin(); | |
2395 | |
2396 // Skip unused arguments. | |
2397 for (int i = 0; i < start_index; i++) { | |
2398 ++parameters_it; | |
2399 } | |
2400 | |
2401 // Actually allocate the backing store. | |
2402 AllocationBuilder a(jsgraph(), effect, control); | |
2403 a.AllocateArray(num_elements, factory()->fixed_array_map()); | |
2404 for (int i = 0; i < num_elements; ++i, ++parameters_it) { | |
2405 a.Store(AccessBuilder::ForFixedArraySlot(i), (*parameters_it).node); | |
2406 } | |
2407 return a.Finish(); | |
2408 } | |
2409 | |
2410 | |
2411 // Helper that allocates a FixedArray serving as a parameter map for values | |
2412 // recorded in the given {frame_state}. Some elements map to slots within the | |
2413 // given {context}. Serves as backing store for JSCreateArguments nodes. | |
2414 Node* JSTypedLowering::AllocateAliasedArguments( | |
2415 Node* effect, Node* control, Node* frame_state, Node* context, | |
2416 Handle<SharedFunctionInfo> shared, bool* has_aliased_arguments) { | |
2417 FrameStateInfo state_info = OpParameter<FrameStateInfo>(frame_state); | |
2418 int argument_count = state_info.parameter_count() - 1; // Minus receiver. | |
2419 if (argument_count == 0) return jsgraph()->EmptyFixedArrayConstant(); | |
2420 | |
2421 // If there is no aliasing, the arguments object elements are not special in | |
2422 // any way, we can just return an unmapped backing store instead. | |
2423 int parameter_count = shared->internal_formal_parameter_count(); | |
2424 if (parameter_count == 0) { | |
2425 return AllocateArguments(effect, control, frame_state); | |
2426 } | |
2427 | |
2428 // Calculate number of argument values being aliased/mapped. | |
2429 int mapped_count = Min(argument_count, parameter_count); | |
2430 *has_aliased_arguments = true; | |
2431 | |
2432 // Prepare an iterator over argument values recorded in the frame state. | |
2433 Node* const parameters = frame_state->InputAt(kFrameStateParametersInput); | |
2434 StateValuesAccess parameters_access(parameters); | |
2435 auto paratemers_it = ++parameters_access.begin(); | |
2436 | |
2437 // The unmapped argument values recorded in the frame state are stored yet | |
2438 // another indirection away and then linked into the parameter map below, | |
2439 // whereas mapped argument values are replaced with a hole instead. | |
2440 AllocationBuilder aa(jsgraph(), effect, control); | |
2441 aa.AllocateArray(argument_count, factory()->fixed_array_map()); | |
2442 for (int i = 0; i < mapped_count; ++i, ++paratemers_it) { | |
2443 aa.Store(AccessBuilder::ForFixedArraySlot(i), jsgraph()->TheHoleConstant()); | |
2444 } | |
2445 for (int i = mapped_count; i < argument_count; ++i, ++paratemers_it) { | |
2446 aa.Store(AccessBuilder::ForFixedArraySlot(i), (*paratemers_it).node); | |
2447 } | |
2448 Node* arguments = aa.Finish(); | |
2449 | |
2450 // Actually allocate the backing store. | |
2451 AllocationBuilder a(jsgraph(), arguments, control); | |
2452 a.AllocateArray(mapped_count + 2, factory()->sloppy_arguments_elements_map()); | |
2453 a.Store(AccessBuilder::ForFixedArraySlot(0), context); | |
2454 a.Store(AccessBuilder::ForFixedArraySlot(1), arguments); | |
2455 for (int i = 0; i < mapped_count; ++i) { | |
2456 int idx = Context::MIN_CONTEXT_SLOTS + parameter_count - 1 - i; | |
2457 a.Store(AccessBuilder::ForFixedArraySlot(i + 2), jsgraph()->Constant(idx)); | |
2458 } | |
2459 return a.Finish(); | |
2460 } | |
2461 | |
2462 | |
2463 Node* JSTypedLowering::AllocateElements(Node* effect, Node* control, | |
2464 ElementsKind elements_kind, | |
2465 int capacity, PretenureFlag pretenure) { | |
2466 DCHECK_LE(1, capacity); | |
2467 DCHECK_LE(capacity, JSArray::kInitialMaxFastElementArray); | |
2468 | |
2469 Handle<Map> elements_map = IsFastDoubleElementsKind(elements_kind) | |
2470 ? factory()->fixed_double_array_map() | |
2471 : factory()->fixed_array_map(); | |
2472 ElementAccess access = IsFastDoubleElementsKind(elements_kind) | |
2473 ? AccessBuilder::ForFixedDoubleArrayElement() | |
2474 : AccessBuilder::ForFixedArrayElement(); | |
2475 Node* value = | |
2476 IsFastDoubleElementsKind(elements_kind) | |
2477 ? jsgraph()->Float64Constant(bit_cast<double>(kHoleNanInt64)) | |
2478 : jsgraph()->TheHoleConstant(); | |
2479 | |
2480 // Actually allocate the backing store. | |
2481 AllocationBuilder a(jsgraph(), effect, control); | |
2482 a.AllocateArray(capacity, elements_map, pretenure); | |
2483 for (int i = 0; i < capacity; ++i) { | |
2484 Node* index = jsgraph()->Constant(i); | |
2485 a.Store(access, index, value); | |
2486 } | |
2487 return a.Finish(); | |
2488 } | |
2489 | |
2490 | |
2491 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } | 1762 Factory* JSTypedLowering::factory() const { return jsgraph()->factory(); } |
2492 | 1763 |
2493 | 1764 |
2494 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); } | 1765 Graph* JSTypedLowering::graph() const { return jsgraph()->graph(); } |
2495 | 1766 |
2496 | 1767 |
2497 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); } | 1768 Isolate* JSTypedLowering::isolate() const { return jsgraph()->isolate(); } |
2498 | 1769 |
2499 | 1770 |
2500 JSOperatorBuilder* JSTypedLowering::javascript() const { | 1771 JSOperatorBuilder* JSTypedLowering::javascript() const { |
(...skipping 16 matching lines...) Expand all Loading... |
2517 } | 1788 } |
2518 | 1789 |
2519 | 1790 |
2520 CompilationDependencies* JSTypedLowering::dependencies() const { | 1791 CompilationDependencies* JSTypedLowering::dependencies() const { |
2521 return dependencies_; | 1792 return dependencies_; |
2522 } | 1793 } |
2523 | 1794 |
2524 } // namespace compiler | 1795 } // namespace compiler |
2525 } // namespace internal | 1796 } // namespace internal |
2526 } // namespace v8 | 1797 } // namespace v8 |
OLD | NEW |