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 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 |