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 1441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1452 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( | 1452 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( |
1453 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { | 1453 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { |
1454 CSA_ASSERT(this, IsFixedDoubleArray(object)); | 1454 CSA_ASSERT(this, IsFixedDoubleArray(object)); |
1455 Node* offset = | 1455 Node* offset = |
1456 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, | 1456 ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode, |
1457 FixedArray::kHeaderSize - kHeapObjectTag); | 1457 FixedArray::kHeaderSize - kHeapObjectTag); |
1458 MachineRepresentation rep = MachineRepresentation::kFloat64; | 1458 MachineRepresentation rep = MachineRepresentation::kFloat64; |
1459 return StoreNoWriteBarrier(rep, object, offset, value); | 1459 return StoreNoWriteBarrier(rep, object, offset, value); |
1460 } | 1460 } |
1461 | 1461 |
1462 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context, | 1462 Node* CodeStubAssembler::EnsureArrayPushable(Node* receiver, Label* bailout) { |
1463 Node* array, | 1463 // Disallow pushing onto prototypes. It might be the JSArray prototype. |
1464 // Disallow pushing onto non-extensible objects. | |
1465 Comment("Disallow pushing onto prototypes"); | |
1466 Node* map = LoadMap(receiver); | |
1467 Node* bit_field2 = LoadMapBitField2(map); | |
1468 int mask = static_cast<int>(Map::IsPrototypeMapBits::kMask) | | |
1469 (1 << Map::kIsExtensible); | |
1470 Node* test = Word32And(bit_field2, Int32Constant(mask)); | |
1471 GotoIf(Word32NotEqual(test, Int32Constant(1 << Map::kIsExtensible)), bailout); | |
1472 | |
1473 // Disallow pushing onto arrays in dictionary named property mode. We need | |
1474 // to figure out whether the length property is still writable. | |
1475 Comment("Disallow pushing onto arrays in dictionary named property mode"); | |
1476 GotoIf(IsDictionaryMap(map), bailout); | |
1477 | |
1478 // Check whether the length property is writable. The length property is the | |
1479 // only default named property on arrays. It's nonconfigurable, hence is | |
1480 // guaranteed to stay the first property. | |
1481 Node* descriptors = LoadMapDescriptors(map); | |
1482 Node* details = | |
1483 LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); | |
1484 GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout); | |
1485 | |
1486 Node* kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); | |
1487 return kind; | |
1488 } | |
1489 | |
1490 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | |
1464 CodeStubArguments& args, | 1491 CodeStubArguments& args, |
1465 Variable& arg_index, | 1492 Variable& arg_index, |
1466 Label* bailout) { | 1493 Label* bailout) { |
1467 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | 1494 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); |
1468 Label pre_bailout(this); | 1495 Label pre_bailout(this); |
1469 Label success(this); | 1496 Label success(this); |
1470 Variable var_tagged_length(this, MachineRepresentation::kTagged); | 1497 Variable var_tagged_length(this, MachineRepresentation::kTagged); |
1471 ParameterMode mode = OptimalParameterMode(); | 1498 ParameterMode mode = OptimalParameterMode(); |
1472 Variable var_length(this, OptimalParameterRepresentation(), | 1499 Variable var_length(this, OptimalParameterRepresentation(), |
1473 TaggedToParameter(LoadJSArrayLength(array), mode)); | 1500 TaggedToParameter(LoadJSArrayLength(array), mode)); |
(...skipping 16 matching lines...) Expand all Loading... | |
1490 Goto(&fits); | 1517 Goto(&fits); |
1491 Bind(&fits); | 1518 Bind(&fits); |
1492 Node* elements = var_elements.value(); | 1519 Node* elements = var_elements.value(); |
1493 | 1520 |
1494 // Push each argument onto the end of the array now that there is enough | 1521 // Push each argument onto the end of the array now that there is enough |
1495 // capacity. | 1522 // capacity. |
1496 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); | 1523 CodeStubAssembler::VariableList push_vars({&var_length}, zone()); |
1497 args.ForEach( | 1524 args.ForEach( |
1498 push_vars, | 1525 push_vars, |
1499 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { | 1526 [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) { |
1500 if (IsFastSmiElementsKind(kind)) { | 1527 TryStoreArrayElement(kind, mode, &pre_bailout, elements, |
1501 GotoIf(TaggedIsNotSmi(arg), &pre_bailout); | 1528 var_length.value(), arg); |
1502 } else if (IsFastDoubleElementsKind(kind)) { | |
1503 GotoIfNotNumber(arg, &pre_bailout); | |
1504 } | |
1505 if (IsFastDoubleElementsKind(kind)) { | |
1506 Node* double_value = ChangeNumberToFloat64(arg); | |
1507 StoreFixedDoubleArrayElement(elements, var_length.value(), | |
1508 Float64SilenceNaN(double_value), mode); | |
1509 } else { | |
1510 WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind) | |
1511 ? SKIP_WRITE_BARRIER | |
1512 : UPDATE_WRITE_BARRIER; | |
1513 StoreFixedArrayElement(elements, var_length.value(), arg, | |
1514 barrier_mode, 0, mode); | |
1515 } | |
1516 Increment(var_length, 1, mode); | 1529 Increment(var_length, 1, mode); |
1517 }, | 1530 }, |
1518 first, nullptr); | 1531 first, nullptr); |
1519 { | 1532 { |
1520 Node* length = ParameterToTagged(var_length.value(), mode); | 1533 Node* length = ParameterToTagged(var_length.value(), mode); |
1521 var_tagged_length.Bind(length); | 1534 var_tagged_length.Bind(length); |
1522 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1535 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1523 Goto(&success); | 1536 Goto(&success); |
1524 } | 1537 } |
1525 | 1538 |
1526 Bind(&pre_bailout); | 1539 Bind(&pre_bailout); |
1527 { | 1540 { |
1528 Node* length = ParameterToTagged(var_length.value(), mode); | 1541 Node* length = ParameterToTagged(var_length.value(), mode); |
1529 var_tagged_length.Bind(length); | 1542 var_tagged_length.Bind(length); |
1530 Node* diff = SmiSub(length, LoadJSArrayLength(array)); | 1543 Node* diff = SmiSub(length, LoadJSArrayLength(array)); |
1531 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | 1544 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); |
1532 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); | 1545 arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff))); |
1533 Goto(bailout); | 1546 Goto(bailout); |
1534 } | 1547 } |
1535 | 1548 |
1536 Bind(&success); | 1549 Bind(&success); |
1537 return var_tagged_length.value(); | 1550 return var_tagged_length.value(); |
1538 } | 1551 } |
1539 | 1552 |
1553 void CodeStubAssembler::TryStoreArrayElement(ElementsKind kind, | |
1554 ParameterMode mode, Label* bailout, | |
1555 Node* elements, Node* index, | |
1556 Node* value) { | |
1557 if (IsFastSmiElementsKind(kind)) { | |
1558 GotoIf(TaggedIsNotSmi(value), bailout); | |
1559 } else if (IsFastDoubleElementsKind(kind)) { | |
1560 GotoIfNotNumber(value, bailout); | |
1561 } | |
1562 if (IsFastDoubleElementsKind(kind)) { | |
1563 Node* double_value = ChangeNumberToFloat64(value); | |
1564 StoreFixedDoubleArrayElement(elements, index, | |
1565 Float64SilenceNaN(double_value), mode); | |
1566 } else { | |
1567 WriteBarrierMode barrier_mode = | |
1568 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | |
1569 StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode); | |
1570 } | |
1571 } | |
1572 | |
1573 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* array, | |
1574 Node* value, Label* bailout) { | |
1575 Comment("BuildAppendJSArray: %s", ElementsKindToString(kind)); | |
1576 Label success(this); | |
1577 Variable var_tagged_length(this, MachineRepresentation::kTagged); | |
1578 ParameterMode mode = OptimalParameterMode(); | |
1579 Variable var_length(this, OptimalParameterRepresentation(), | |
1580 TaggedToParameter(LoadJSArrayLength(array), mode)); | |
1581 Variable var_elements(this, MachineRepresentation::kTagged, | |
1582 LoadElements(array)); | |
1583 Node* capacity = | |
1584 TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode); | |
1585 | |
1586 // Resize the capacity of the fixed array if it doesn't fit. | |
1587 Label fits(this, &var_elements); | |
1588 Node* growth = IntPtrOrSmiConstant(1, mode); | |
danno
2017/04/03 15:35:27
This prologue and grow code looks quite similar be
mvstanton
2017/04/06 08:57:36
Done.
| |
1589 Node* new_length = IntPtrOrSmiAdd(growth, var_length.value(), mode); | |
1590 GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits); | |
1591 Node* new_capacity = CalculateNewElementsCapacity(new_length, mode); | |
1592 var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind, | |
1593 kind, capacity, new_capacity, mode, | |
1594 bailout)); | |
1595 Goto(&fits); | |
1596 Bind(&fits); | |
1597 Node* elements = var_elements.value(); | |
1598 | |
1599 // Push each argument onto the end of the array now that there is enough | |
1600 // capacity. | |
1601 TryStoreArrayElement(kind, mode, bailout, elements, var_length.value(), | |
1602 value); | |
1603 Increment(var_length, 1, mode); | |
1604 | |
1605 { | |
1606 Node* length = ParameterToTagged(var_length.value(), mode); | |
1607 var_tagged_length.Bind(length); | |
1608 StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length); | |
1609 Goto(&success); | |
1610 } | |
1611 | |
1612 Bind(&success); | |
1613 return var_tagged_length.value(); | |
1614 } | |
1615 | |
1540 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { | 1616 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) { |
1541 Node* result = Allocate(HeapNumber::kSize, kNone); | 1617 Node* result = Allocate(HeapNumber::kSize, kNone); |
1542 Heap::RootListIndex heap_map_index = | 1618 Heap::RootListIndex heap_map_index = |
1543 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex | 1619 mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex |
1544 : Heap::kMutableHeapNumberMapRootIndex; | 1620 : Heap::kMutableHeapNumberMapRootIndex; |
1545 StoreMapNoWriteBarrier(result, heap_map_index); | 1621 StoreMapNoWriteBarrier(result, heap_map_index); |
1546 return result; | 1622 return result; |
1547 } | 1623 } |
1548 | 1624 |
1549 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, | 1625 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value, |
(...skipping 6898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8448 formatted.c_str(), TENURED); | 8524 formatted.c_str(), TENURED); |
8449 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 8525 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
8450 HeapConstant(string)); | 8526 HeapConstant(string)); |
8451 } | 8527 } |
8452 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 8528 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
8453 #endif | 8529 #endif |
8454 } | 8530 } |
8455 | 8531 |
8456 } // namespace internal | 8532 } // namespace internal |
8457 } // namespace v8 | 8533 } // namespace v8 |
OLD | NEW |