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 1460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1471 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( | 1471 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( |
1472 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { | 1472 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { |
1473 CSA_ASSERT(this, IsFixedDoubleArray(object)); | 1473 CSA_ASSERT(this, IsFixedDoubleArray(object)); |
1474 Node* offset = | 1474 Node* offset = |
1475 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, | 1475 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, |
1476 FixedArray::kHeaderSize - kHeapObjectTag); | 1476 FixedArray::kHeaderSize - kHeapObjectTag); |
1477 MachineRepresentation rep = MachineRepresentation::kFloat64; | 1477 MachineRepresentation rep = MachineRepresentation::kFloat64; |
1478 return StoreNoWriteBarrier(rep, object, offset, value); | 1478 return StoreNoWriteBarrier(rep, object, offset, value); |
1479 } | 1479 } |
1480 | 1480 |
1481 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 1481 Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) { |
1482 Node* array, | 1482 // Disallow pushing onto prototypes. It might be the JSArray prototype. |
1483 // Disallow pushing onto non-extensible objects. | |
1484 Comment("Disallow pushing onto prototypes"); | |
1485 Node* map = LoadMap(receiver); | |
1486 Node* bit_field2 = LoadMapBitField2(map); | |
1487 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | | |
1488 (1 << Map::kIsExtensible); | |
1489 Node* test = Word32And(bit_field2, Int32Constant(mask)); | |
1490 GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout); | |
1491 | |
1492 // Disallow pushing onto arrays in dictionary named property mode. We need | |
1493 // to figure out whether the length property is still writable. | |
1494 Comment("Disallow pushing onto arrays in dictionary named property mode"); | |
1495 GotoIf(IsDictionaryMap(map), bailout); | |
1496 | |
1497 // Check whether the length property is writable. The length property is the | |
1498 // only default named property on arrays. It's nonconfigurable, hence is | |
1499 // guaranteed to stay the first property. | |
1500 Node* descriptors = LoadMapDescriptors(map); | |
1501 Node* details = | |
1502 LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); | |
1503 GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout); | |
1504 | |
1505 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | |
1506 return kind; | |
1507 } | |
1508 | |
1509 Node* CodeStubAssembler::PossiblyGrowElementsCapacity( | |
1510 ParameterMode mode, ElementsKind kind, Node* array, Node* length, | |
1511 Node* elements, Node* growth, Label* fits, Label* bailout) { | |
1512 Node* capacity = TaggedToParameter(LoadFixedArrayBaseLength(elements), mode); | |
1513 Node* new_length = | |
1514 IntPtrOrSmiAdd(WordToParameter(growth, mode), length, mode); | |
1515 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), fits); | |
1516 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | |
1517 return GrowElementsCapacity(array, elements, kind, kind, capacity, | |
1518 new_capacity, mode, bailout); | |
1519 } | |
1520 | |
1521 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | |
1483 CodeStubArguments& args, | 1522 CodeStubArguments& args, |
1484 Variable& arg_index, | 1523 Variable& arg_index, |
1485 Label* bailout) { | 1524 Label* bailout) { |
1486 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | 1525 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); |
1487 Label pre_bailout(this); | 1526 Label pre_bailout(this); |
1488 Label success(this); | 1527 Label success(this); |
1489 Variable var_tagged_length(this, MachineRepresentation::kTagged); | 1528 Variable var_tagged_length(this, MachineRepresentation::kTagged); |
1490 ParameterMode mode = OptimalParameterMode(); | 1529 ParameterMode mode = OptimalParameterMode(); |
1491 Variable var_length(this, OptimalParameterRepresentation(), | 1530 Variable var_length(this, OptimalParameterRepresentation(), |
1492 TaggedToParameter(LoadJSArrayLength(array), mode)); | 1531 TaggedToParameter(LoadJSArrayLength(array), mode)); |
1493 Variable var_elements(this, MachineRepresentation::kTagged, | 1532 Variable var_elements(this, MachineRepresentation::kTagged, |
1494 LoadElements(array)); | 1533 LoadElements(array)); |
1495 Node* capacity = | |
1496 TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); | |
1497 | 1534 |
1498 // Resize the capacity of the fixed array if it doesn't fit. | 1535 // Resize the capacity of the fixed array if it doesn't fit. |
1499 Label fits(this, &var_elements); | 1536 Label fits(this, &var_elements); |
1500 Node* first = arg_index.value(); | 1537 Node* first = arg_index.value(); |
1501 Node* growth = IntPtrSub(args.GetLength(), first); | 1538 Node* growth = IntPtrSub(args.GetLength(), first); |
1502 Node* new_length = | 1539 var_elements.Bind(PossiblyGrowElementsCapacity( |
1503 IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode); | 1540 mode, kind, array, var_length.value(), var_elements.value(), growth, |
1504 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | 1541 &fits, &pre_bailout)); |
1505 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | |
1506 var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, | |
1507 kind, capacity, new_capacity, mode, | |
1508 &pre_bailout)); | |
1509 Goto(&fits); | 1542 Goto(&fits); |
1510 Bind(&fits); | 1543 Bind(&fits); |
1511 Node* elements = var_elements.value(); | 1544 Node* elements = var_elements.value(); |
1512 | 1545 |
1513 // Push each argument onto the end of the array now that there is enough | 1546 // Push each argument onto the end of the array now that there is enough |
1514 // capacity. | 1547 // capacity. |
1515 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); | 1548 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); |
1516 args.ForEach( | 1549 args.ForEach( |
1517 push_vars, | 1550 push_vars, |
1518 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { | 1551 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { |
1519 if (IsFastSmiElementsKind(kind)) { | 1552 TryStoreArrayElement(kind, mode, &pre_bailout, elements, |
1520 GotoIf(TaggedIsNotSmi(arg), &pre_bailout); | 1553 var_length.value(), arg); |
1521 } else if (IsFastDoubleElementsKind(kind)) { | |
1522 GotoIfNotNumber(arg, &pre_bailout); | |
1523 } | |
1524 if (IsFastDoubleElementsKind(kind)) { | |
1525 Node* double_value = ChangeNumberToFloat64(arg); | |
1526 StoreFixedDoubleArrayElement(elements, var_length.value(), | |
1527 Float64SilenceNaN(double_value), mode); | |
1528 } else { | |
1529 WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) | |
1530 ? SKIP_WRITE_BARRIER | |
1531 : UPDATE_WRITE_BARRIER; | |
1532 StoreFixedArrayElement(elements, var_length.value(), arg, | |
1533 barrier_mode, 0, mode); | |
1534 } | |
1535 Increment(var_length, 1, mode); | 1554 Increment(var_length, 1, mode); |
1536 }, | 1555 }, |
1537 first, nullptr); | 1556 first, nullptr); |
1538 { | 1557 { |
1539 Node* length = ParameterToTagged(var_length.value(), mode); | 1558 Node* length = ParameterToTagged(var_length.value(), mode); |
1540 var_tagged_length.Bind(length); | 1559 var_tagged_length.Bind(length); |
1541 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1560 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1542 Goto(&success); | 1561 Goto(&success); |
1543 } | 1562 } |
1544 | 1563 |
1545 Bind(&pre_bailout); | 1564 Bind(&pre_bailout); |
1546 { | 1565 { |
1547 Node* length = ParameterToTagged(var_length.value(), mode); | 1566 Node* length = ParameterToTagged(var_length.value(), mode); |
1548 var_tagged_length.Bind(length); | 1567 var_tagged_length.Bind(length); |
1549 Node* diff = SmiSub(length, LoadJSArrayLength(array)); | 1568 Node* diff = SmiSub(length, LoadJSArrayLength(array)); |
1550 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1569 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1551 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); | 1570 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); |
1552 Goto(bailout); | 1571 Goto(bailout); |
1553 } | 1572 } |
1554 | 1573 |
1555 Bind(&success); | 1574 Bind(&success); |
1556 return var_tagged_length.value(); | 1575 return var_tagged_length.value(); |
1557 } | 1576 } |
1558 | 1577 |
1578 void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind, | |
1579 ParameterMode mode, Label* bailout, | |
1580 Node* elements, Node* index, | |
1581 Node* value) { | |
1582 if (IsFastSmiElementsKind(kind)) { | |
1583 GotoIf(TaggedIsNotSmi(value), bailout); | |
1584 } else if (IsFastDoubleElementsKind(kind)) { | |
1585 GotoIfNotNumber(value, bailout); | |
1586 } | |
1587 if (IsFastDoubleElementsKind(kind)) { | |
1588 Node* double_value = ChangeNumberToFloat64(value); | |
1589 StoreFixedDoubleArrayElement(elements, index, | |
1590 Float64SilenceNaN(double_value), mode); | |
1591 } else { | |
1592 WriteBarrierMode barrier_mode = | |
1593 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | |
1594 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); | |
1595 } | |
1596 } | |
1597 | |
1598 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | |
1599 Node* value, Label* bailout) { | |
1600 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | |
1601 Label success(this); | |
1602 Variable var_tagged_length(this, MachineRepresentation::kTagged); | |
jgruber
2017/04/19 10:25:28
Nit: VARIABLE(var_x, ...) instead of Variable var_
mvstanton
2017/04/23 09:00:09
Done.
| |
1603 ParameterMode mode = OptimalParameterMode(); | |
1604 Variable var_length(this, OptimalParameterRepresentation(), | |
1605 TaggedToParameter(LoadJSArrayLength(array), mode)); | |
1606 Variable var_elements(this, MachineRepresentation::kTagged, | |
1607 LoadElements(array)); | |
1608 | |
1609 // Resize the capacity of the fixed array if it doesn't fit. | |
1610 Label fits(this, &var_elements); | |
1611 Node* growth = IntPtrOrSmiConstant(1, mode); | |
1612 var_elements.Bind(PossiblyGrowElementsCapacity( | |
1613 mode, kind, array, var_length.value(), var_elements.value(), growth, | |
1614 &fits, bailout)); | |
1615 /* | |
1616 Node* new_length = IntPtrOrSmiAdd(growth, var_length.value(), mode); | |
jgruber
2017/04/19 10:25:28
Nit: Leftover code?
mvstanton
2017/04/23 09:00:09
Done.
| |
1617 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | |
1618 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | |
1619 var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, | |
1620 kind, capacity, new_capacity, mode, | |
1621 bailout)); | |
1622 */ | |
1623 Goto(&fits); | |
1624 Bind(&fits); | |
1625 Node* elements = var_elements.value(); | |
1626 | |
1627 // Push each argument onto the end of the array now that there is enough | |
1628 // capacity. | |
1629 TryStoreArrayElement(kind, mode, bailout, elements, var_length.value(), | |
1630 value); | |
1631 Increment(var_length, 1, mode); | |
1632 | |
1633 { | |
1634 Node* length = ParameterToTagged(var_length.value(), mode); | |
1635 var_tagged_length.Bind(length); | |
jgruber
2017/04/19 10:25:28
Nit: var_tagged_length and the success label aren'
mvstanton
2017/04/23 09:00:09
Good idea, thanks!
| |
1636 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | |
1637 Goto(&success); | |
1638 } | |
1639 | |
1640 Bind(&success); | |
1641 return var_tagged_length.value(); | |
1642 } | |
1643 | |
1559 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { | 1644 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { |
1560 Node* result = Allocate(HeapNumber::kSize, kNone); | 1645 Node* result = Allocate(HeapNumber::kSize, kNone); |
1561 Heap::RootListIndex heap_map_index = | 1646 Heap::RootListIndex heap_map_index = |
1562 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex | 1647 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex |
1563 : Heap::kMutableHeapNumberMapRootIndex; | 1648 : Heap::kMutableHeapNumberMapRootIndex; |
1564 StoreMapNoWriteBarrier(result, heap_map_index); | 1649 StoreMapNoWriteBarrier(result, heap_map_index); |
1565 return result; | 1650 return result; |
1566 } | 1651 } |
1567 | 1652 |
1568 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, | 1653 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, |
(...skipping 6793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8362 | 8447 |
8363 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); | 8448 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1)); |
8364 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); | 8449 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1)); |
8365 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); | 8450 STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1)); |
8366 | 8451 |
8367 // Check prototype chain if receiver does not have packed elements. | 8452 // Check prototype chain if receiver does not have packed elements. |
8368 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); | 8453 Node* holey_elements = Word32And(elements_kind, Int32Constant(1)); |
8369 return Word32Equal(holey_elements, Int32Constant(1)); | 8454 return Word32Equal(holey_elements, Int32Constant(1)); |
8370 } | 8455 } |
8371 | 8456 |
8457 Node* CodeStubAssembler::IsElementsKindGreaterThan( | |
8458 Node* target_kind, ElementsKind reference_kind) { | |
8459 return Int32GreaterThan(target_kind, Int32Constant(reference_kind)); | |
8460 } | |
8461 | |
8372 Node* CodeStubAssembler::IsDebugActive() { | 8462 Node* CodeStubAssembler::IsDebugActive() { |
8373 Node* is_debug_active = Load( | 8463 Node* is_debug_active = Load( |
8374 MachineType::Uint8(), | 8464 MachineType::Uint8(), |
8375 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); | 8465 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); |
8376 return Word32NotEqual(is_debug_active, Int32Constant(0)); | 8466 return Word32NotEqual(is_debug_active, Int32Constant(0)); |
8377 } | 8467 } |
8378 | 8468 |
8379 Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() { | 8469 Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() { |
8380 Node* const promise_hook_or_debug_is_active = | 8470 Node* const promise_hook_or_debug_is_active = |
8381 Load(MachineType::Uint8(), | 8471 Load(MachineType::Uint8(), |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8467 formatted.c_str(), TENURED); | 8557 formatted.c_str(), TENURED); |
8468 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8558 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
8469 HeapConstant(string)); | 8559 HeapConstant(string)); |
8470 } | 8560 } |
8471 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8561 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
8472 #endif | 8562 #endif |
8473 } | 8563 } |
8474 | 8564 |
8475 } // namespace internal | 8565 } // namespace internal |
8476 } // namespace v8 | 8566 } // namespace v8 |
OLD | NEW |