Chromium Code Reviews| 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 |