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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( | 1516 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( |
1517 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { | 1517 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { |
1518 CSA_ASSERT(this, IsFixedDoubleArray(object)); | 1518 CSA_ASSERT(this, IsFixedDoubleArray(object)); |
1519 Node* offset = | 1519 Node* offset = |
1520 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, | 1520 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, |
1521 FixedArray::kHeaderSize - kHeapObjectTag); | 1521 FixedArray::kHeaderSize - kHeapObjectTag); |
1522 MachineRepresentation rep = MachineRepresentation::kFloat64; | 1522 MachineRepresentation rep = MachineRepresentation::kFloat64; |
1523 return StoreNoWriteBarrier(rep, object, offset, value); | 1523 return StoreNoWriteBarrier(rep, object, offset, value); |
1524 } | 1524 } |
1525 | 1525 |
1526 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 1526 Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) { |
1527 Node* array, | 1527 // Disallow pushing onto prototypes. It might be the JSArray prototype. |
| 1528 // Disallow pushing onto non-extensible objects. |
| 1529 Comment("Disallow pushing onto prototypes"); |
| 1530 Node* map = LoadMap(receiver); |
| 1531 Node* bit_field2 = LoadMapBitField2(map); |
| 1532 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | |
| 1533 (1 << Map::kIsExtensible); |
| 1534 Node* test = Word32And(bit_field2, Int32Constant(mask)); |
| 1535 GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout); |
| 1536 |
| 1537 // Disallow pushing onto arrays in dictionary named property mode. We need |
| 1538 // to figure out whether the length property is still writable. |
| 1539 Comment("Disallow pushing onto arrays in dictionary named property mode"); |
| 1540 GotoIf(IsDictionaryMap(map), bailout); |
| 1541 |
| 1542 // Check whether the length property is writable. The length property is the |
| 1543 // only default named property on arrays. It's nonconfigurable, hence is |
| 1544 // guaranteed to stay the first property. |
| 1545 Node* descriptors = LoadMapDescriptors(map); |
| 1546 Node* details = |
| 1547 LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); |
| 1548 GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout); |
| 1549 |
| 1550 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); |
| 1551 return kind; |
| 1552 } |
| 1553 |
| 1554 void CodeStubAssembler::PossiblyGrowElementsCapacity( |
| 1555 ParameterMode mode, ElementsKind kind, Node* array, Node* length, |
| 1556 Variable* var_elements, Node* growth, Label* bailout) { |
| 1557 Label fits(this, var_elements); |
| 1558 Node* capacity = |
| 1559 TaggedToParameter(LoadFixedArrayBaseLength(var_elements->value()), mode); |
| 1560 // length and growth nodes are already in a ParameterMode appropriate |
| 1561 // representation. |
| 1562 Node* new_length = IntPtrOrSmiAdd(growth, length, mode); |
| 1563 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); |
| 1564 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); |
| 1565 var_elements->Bind(GrowElementsCapacity(array, var_elements->value(), kind, |
| 1566 kind, capacity, new_capacity, mode, |
| 1567 bailout)); |
| 1568 Goto(&fits); |
| 1569 BIND(&fits); |
| 1570 } |
| 1571 |
| 1572 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, |
1528 CodeStubArguments& args, | 1573 CodeStubArguments& args, |
1529 Variable& arg_index, | 1574 Variable& arg_index, |
1530 Label* bailout) { | 1575 Label* bailout) { |
1531 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | 1576 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); |
1532 Label pre_bailout(this); | 1577 Label pre_bailout(this); |
1533 Label success(this); | 1578 Label success(this); |
1534 VARIABLE(var_tagged_length, MachineRepresentation::kTagged); | 1579 VARIABLE(var_tagged_length, MachineRepresentation::kTagged); |
1535 ParameterMode mode = OptimalParameterMode(); | 1580 ParameterMode mode = OptimalParameterMode(); |
1536 VARIABLE(var_length, OptimalParameterRepresentation(), | 1581 VARIABLE(var_length, OptimalParameterRepresentation(), |
1537 TaggedToParameter(LoadJSArrayLength(array), mode)); | 1582 TaggedToParameter(LoadJSArrayLength(array), mode)); |
1538 VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); | 1583 VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); |
1539 Node* capacity = | |
1540 TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); | |
1541 | 1584 |
1542 // Resize the capacity of the fixed array if it doesn't fit. | 1585 // Resize the capacity of the fixed array if it doesn't fit. |
1543 Label fits(this, &var_elements); | |
1544 Node* first = arg_index.value(); | 1586 Node* first = arg_index.value(); |
1545 Node* growth = IntPtrSub(args.GetLength(), first); | 1587 Node* growth = WordToParameter(IntPtrSub(args.GetLength(), first), mode); |
1546 Node* new_length = | 1588 PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(), |
1547 IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode); | 1589 &var_elements, growth, &pre_bailout); |
1548 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | |
1549 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | |
1550 var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, | |
1551 kind, capacity, new_capacity, mode, | |
1552 &pre_bailout)); | |
1553 Goto(&fits); | |
1554 BIND(&fits); | |
1555 Node* elements = var_elements.value(); | |
1556 | 1590 |
1557 // Push each argument onto the end of the array now that there is enough | 1591 // Push each argument onto the end of the array now that there is enough |
1558 // capacity. | 1592 // capacity. |
1559 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); | 1593 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); |
| 1594 Node* elements = var_elements.value(); |
1560 args.ForEach( | 1595 args.ForEach( |
1561 push_vars, | 1596 push_vars, |
1562 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { | 1597 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { |
1563 if (IsFastSmiElementsKind(kind)) { | 1598 TryStoreArrayElement(kind, mode, &pre_bailout, elements, |
1564 GotoIf(TaggedIsNotSmi(arg), &pre_bailout); | 1599 var_length.value(), arg); |
1565 } else if (IsFastDoubleElementsKind(kind)) { | |
1566 GotoIfNotNumber(arg, &pre_bailout); | |
1567 } | |
1568 if (IsFastDoubleElementsKind(kind)) { | |
1569 Node* double_value = ChangeNumberToFloat64(arg); | |
1570 StoreFixedDoubleArrayElement(elements, var_length.value(), | |
1571 Float64SilenceNaN(double_value), mode); | |
1572 } else { | |
1573 WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) | |
1574 ? SKIP_WRITE_BARRIER | |
1575 : UPDATE_WRITE_BARRIER; | |
1576 StoreFixedArrayElement(elements, var_length.value(), arg, | |
1577 barrier_mode, 0, mode); | |
1578 } | |
1579 Increment(var_length, 1, mode); | 1600 Increment(var_length, 1, mode); |
1580 }, | 1601 }, |
1581 first, nullptr); | 1602 first, nullptr); |
1582 { | 1603 { |
1583 Node* length = ParameterToTagged(var_length.value(), mode); | 1604 Node* length = ParameterToTagged(var_length.value(), mode); |
1584 var_tagged_length.Bind(length); | 1605 var_tagged_length.Bind(length); |
1585 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1606 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1586 Goto(&success); | 1607 Goto(&success); |
1587 } | 1608 } |
1588 | 1609 |
1589 BIND(&pre_bailout); | 1610 BIND(&pre_bailout); |
1590 { | 1611 { |
1591 Node* length = ParameterToTagged(var_length.value(), mode); | 1612 Node* length = ParameterToTagged(var_length.value(), mode); |
1592 var_tagged_length.Bind(length); | 1613 var_tagged_length.Bind(length); |
1593 Node* diff = SmiSub(length, LoadJSArrayLength(array)); | 1614 Node* diff = SmiSub(length, LoadJSArrayLength(array)); |
1594 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1615 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1595 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); | 1616 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); |
1596 Goto(bailout); | 1617 Goto(bailout); |
1597 } | 1618 } |
1598 | 1619 |
1599 BIND(&success); | 1620 BIND(&success); |
1600 return var_tagged_length.value(); | 1621 return var_tagged_length.value(); |
1601 } | 1622 } |
1602 | 1623 |
| 1624 void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind, |
| 1625 ParameterMode mode, Label* bailout, |
| 1626 Node* elements, Node* index, |
| 1627 Node* value) { |
| 1628 if (IsFastSmiElementsKind(kind)) { |
| 1629 GotoIf(TaggedIsNotSmi(value), bailout); |
| 1630 } else if (IsFastDoubleElementsKind(kind)) { |
| 1631 GotoIfNotNumber(value, bailout); |
| 1632 } |
| 1633 if (IsFastDoubleElementsKind(kind)) { |
| 1634 Node* double_value = ChangeNumberToFloat64(value); |
| 1635 StoreFixedDoubleArrayElement(elements, index, |
| 1636 Float64SilenceNaN(double_value), mode); |
| 1637 } else { |
| 1638 WriteBarrierMode barrier_mode = |
| 1639 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
| 1640 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); |
| 1641 } |
| 1642 } |
| 1643 |
| 1644 void CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, |
| 1645 Node* value, Label* bailout) { |
| 1646 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); |
| 1647 ParameterMode mode = OptimalParameterMode(); |
| 1648 VARIABLE(var_length, OptimalParameterRepresentation(), |
| 1649 TaggedToParameter(LoadJSArrayLength(array), mode)); |
| 1650 VARIABLE(var_elements, MachineRepresentation::kTagged, LoadElements(array)); |
| 1651 |
| 1652 // Resize the capacity of the fixed array if it doesn't fit. |
| 1653 Node* growth = IntPtrOrSmiConstant(1, mode); |
| 1654 PossiblyGrowElementsCapacity(mode, kind, array, var_length.value(), |
| 1655 &var_elements, growth, bailout); |
| 1656 |
| 1657 // Push each argument onto the end of the array now that there is enough |
| 1658 // capacity. |
| 1659 TryStoreArrayElement(kind, mode, bailout, var_elements.value(), |
| 1660 var_length.value(), value); |
| 1661 Increment(var_length, 1, mode); |
| 1662 |
| 1663 Node* length = ParameterToTagged(var_length.value(), mode); |
| 1664 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
| 1665 } |
| 1666 |
1603 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { | 1667 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { |
1604 Node* result = Allocate(HeapNumber::kSize, kNone); | 1668 Node* result = Allocate(HeapNumber::kSize, kNone); |
1605 Heap::RootListIndex heap_map_index = | 1669 Heap::RootListIndex heap_map_index = |
1606 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex | 1670 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex |
1607 : Heap::kMutableHeapNumberMapRootIndex; | 1671 : Heap::kMutableHeapNumberMapRootIndex; |
1608 StoreMapNoWriteBarrier(result, heap_map_index); | 1672 StoreMapNoWriteBarrier(result, heap_map_index); |
1609 return result; | 1673 return result; |
1610 } | 1674 } |
1611 | 1675 |
1612 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, | 1676 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, |
(...skipping 6865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8478 | 8542 |
8479 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); | 8543 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); |
8480 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | 8544 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); |
8481 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | 8545 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); |
8482 | 8546 |
8483 // Check prototype chain if receiver does not have packed elements. | 8547 // Check prototype chain if receiver does not have packed elements. |
8484 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); | 8548 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); |
8485 return Word32Equal(holey_elements, Int32Constant(1)); | 8549 return Word32Equal(holey_elements, Int32Constant(1)); |
8486 } | 8550 } |
8487 | 8551 |
| 8552 Node* CodeStubAssembler::IsElementsKindGreaterThan( |
| 8553 Node* target_kind, ElementsKind reference_kind) { |
| 8554 return Int32GreaterThan(target_kind, Int32Constant(reference_kind)); |
| 8555 } |
| 8556 |
8488 Node* CodeStubAssembler::IsDebugActive() { | 8557 Node* CodeStubAssembler::IsDebugActive() { |
8489 Node* is_debug_active = Load( | 8558 Node* is_debug_active = Load( |
8490 MachineType::Uint8(), | 8559 MachineType::Uint8(), |
8491 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); | 8560 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); |
8492 return Word32NotEqual(is_debug_active, Int32Constant(0)); | 8561 return Word32NotEqual(is_debug_active, Int32Constant(0)); |
8493 } | 8562 } |
8494 | 8563 |
8495 Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() { | 8564 Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() { |
8496 Node* const promise_hook_or_debug_is_active = | 8565 Node* const promise_hook_or_debug_is_active = |
8497 Load(MachineType::Uint8(), | 8566 Load(MachineType::Uint8(), |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8583 formatted.c_str(), TENURED); | 8652 formatted.c_str(), TENURED); |
8584 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8653 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
8585 HeapConstant(string)); | 8654 HeapConstant(string)); |
8586 } | 8655 } |
8587 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8656 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
8588 #endif | 8657 #endif |
8589 } | 8658 } |
8590 | 8659 |
8591 } // namespace internal | 8660 } // namespace internal |
8592 } // namespace v8 | 8661 } // namespace v8 |
OLD | NEW |