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 | 4 |
| 5 #include "src/code-stub-assembler.h" | 5 #include "src/code-stub-assembler.h" |
| 6 #include "src/code-factory.h" | 6 #include "src/code-factory.h" |
| 7 #include "src/frames-inl.h" | 7 #include "src/frames-inl.h" |
| 8 #include "src/frames.h" | 8 #include "src/frames.h" |
| 9 #include "src/ic/handler-configuration.h" | 9 #include "src/ic/handler-configuration.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| (...skipping 1420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1431 Heap::RootListIndex value_root_index, ParameterMode mode) { | 1431 Heap::RootListIndex value_root_index, ParameterMode mode) { |
| 1432 bool is_double = IsFastDoubleElementsKind(kind); | 1432 bool is_double = IsFastDoubleElementsKind(kind); |
| 1433 DCHECK(value_root_index == Heap::kTheHoleValueRootIndex || | 1433 DCHECK(value_root_index == Heap::kTheHoleValueRootIndex || |
| 1434 value_root_index == Heap::kUndefinedValueRootIndex); | 1434 value_root_index == Heap::kUndefinedValueRootIndex); |
| 1435 DCHECK_IMPLIES(is_double, value_root_index == Heap::kTheHoleValueRootIndex); | 1435 DCHECK_IMPLIES(is_double, value_root_index == Heap::kTheHoleValueRootIndex); |
| 1436 STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32); | 1436 STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32); |
| 1437 Node* double_hole = | 1437 Node* double_hole = |
| 1438 Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32); | 1438 Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32); |
| 1439 Node* value = LoadRoot(value_root_index); | 1439 Node* value = LoadRoot(value_root_index); |
| 1440 | 1440 |
| 1441 const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag; | 1441 BuildFastFixedArrayForEach( |
| 1442 int32_t to; | 1442 array, kind, from_node, to_node, |
| 1443 bool constant_to = ToInt32Constant(to_node, to); | 1443 [value, is_double, double_hole](CodeStubAssembler* assembler, Node* array, |
| 1444 int32_t from; | 1444 Node* offset) { |
| 1445 bool constant_from = ToInt32Constant(from_node, from); | 1445 if (is_double) { |
| 1446 if (constant_to && constant_from && | 1446 // Don't use doubles to store the hole double, since manipulating the |
| 1447 (to - from) <= kElementLoopUnrollThreshold) { | 1447 // signaling NaN used for the hole in C++, e.g. with bit_cast, will |
| 1448 for (int i = from; i < to; ++i) { | 1448 // change its value on ia32 (the x87 stack is used to return values |
| 1449 Node* index = IntPtrConstant(i); | 1449 // and stores to the stack silently clear the signalling bit). |
| 1450 if (is_double) { | 1450 // |
| 1451 Node* offset = ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS, | 1451 // TODO(danno): When we have a Float32/Float64 wrapper class that |
| 1452 first_element_offset); | 1452 // preserves double bits during manipulation, remove this code/change |
| 1453 // Don't use doubles to store the hole double, since manipulating the | 1453 // this to an indexed Float64 store. |
| 1454 // signaling NaN used for the hole in C++, e.g. with bit_cast, will | 1454 if (assembler->Is64()) { |
| 1455 // change its value on ia32 (the x87 stack is used to return values | 1455 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord64, |
| 1456 // and stores to the stack silently clear the signalling bit). | 1456 array, offset, double_hole); |
| 1457 // | 1457 } else { |
| 1458 // TODO(danno): When we have a Float32/Float64 wrapper class that | 1458 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord32, |
| 1459 // preserves double bits during manipulation, remove this code/change | 1459 array, offset, double_hole); |
| 1460 // this to an indexed Float64 store. | 1460 assembler->StoreNoWriteBarrier( |
| 1461 if (Is64()) { | 1461 MachineRepresentation::kWord32, array, |
| 1462 StoreNoWriteBarrier(MachineRepresentation::kWord64, array, offset, | 1462 assembler->IntPtrAdd(offset, |
| 1463 double_hole); | 1463 assembler->IntPtrConstant(kPointerSize)), |
| 1464 double_hole); | |
| 1465 } | |
| 1464 } else { | 1466 } else { |
| 1465 StoreNoWriteBarrier(MachineRepresentation::kWord32, array, offset, | 1467 assembler->StoreNoWriteBarrier(MachineRepresentation::kTagged, array, |
| 1466 double_hole); | 1468 offset, value); |
| 1467 offset = ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS, | |
| 1468 first_element_offset + kPointerSize); | |
| 1469 StoreNoWriteBarrier(MachineRepresentation::kWord32, array, offset, | |
| 1470 double_hole); | |
| 1471 } | 1469 } |
| 1472 } else { | 1470 }, |
| 1473 StoreFixedArrayElement(array, index, value, SKIP_WRITE_BARRIER, | 1471 mode); |
| 1474 INTPTR_PARAMETERS); | |
| 1475 } | |
| 1476 } | |
| 1477 } else { | |
| 1478 Variable current(this, MachineRepresentation::kTagged); | |
| 1479 Label test(this); | |
| 1480 Label decrement(this, ¤t); | |
| 1481 Label done(this); | |
| 1482 Node* limit = | |
| 1483 IntPtrAdd(array, ElementOffsetFromIndex(from_node, kind, mode)); | |
| 1484 current.Bind(IntPtrAdd(array, ElementOffsetFromIndex(to_node, kind, mode))); | |
| 1485 | |
| 1486 Branch(WordEqual(current.value(), limit), &done, &decrement); | |
| 1487 | |
| 1488 Bind(&decrement); | |
| 1489 current.Bind(IntPtrSub( | |
| 1490 current.value(), | |
| 1491 IntPtrConstant(IsFastDoubleElementsKind(kind) ? kDoubleSize | |
| 1492 : kPointerSize))); | |
| 1493 if (is_double) { | |
| 1494 // Don't use doubles to store the hole double, since manipulating the | |
| 1495 // signaling NaN used for the hole in C++, e.g. with bit_cast, will | |
| 1496 // change its value on ia32 (the x87 stack is used to return values | |
| 1497 // and stores to the stack silently clear the signalling bit). | |
| 1498 // | |
| 1499 // TODO(danno): When we have a Float32/Float64 wrapper class that | |
| 1500 // preserves double bits during manipulation, remove this code/change | |
| 1501 // this to an indexed Float64 store. | |
| 1502 if (Is64()) { | |
| 1503 StoreNoWriteBarrier(MachineRepresentation::kWord64, current.value(), | |
| 1504 Int64Constant(first_element_offset), double_hole); | |
| 1505 } else { | |
| 1506 StoreNoWriteBarrier(MachineRepresentation::kWord32, current.value(), | |
| 1507 Int32Constant(first_element_offset), double_hole); | |
| 1508 StoreNoWriteBarrier(MachineRepresentation::kWord32, current.value(), | |
| 1509 Int32Constant(kPointerSize + first_element_offset), | |
| 1510 double_hole); | |
| 1511 } | |
| 1512 } else { | |
| 1513 StoreNoWriteBarrier(MachineType::PointerRepresentation(), current.value(), | |
| 1514 IntPtrConstant(first_element_offset), value); | |
| 1515 } | |
| 1516 Node* compare = WordNotEqual(current.value(), limit); | |
| 1517 Branch(compare, &decrement, &done); | |
| 1518 | |
| 1519 Bind(&done); | |
| 1520 } | |
| 1521 } | 1472 } |
| 1522 | 1473 |
| 1523 void CodeStubAssembler::CopyFixedArrayElements( | 1474 void CodeStubAssembler::CopyFixedArrayElements( |
| 1524 ElementsKind from_kind, Node* from_array, ElementsKind to_kind, | 1475 ElementsKind from_kind, Node* from_array, ElementsKind to_kind, |
| 1525 Node* to_array, Node* element_count, Node* capacity, | 1476 Node* to_array, Node* element_count, Node* capacity, |
| 1526 WriteBarrierMode barrier_mode, ParameterMode mode) { | 1477 WriteBarrierMode barrier_mode, ParameterMode mode) { |
| 1527 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); | 1478 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); |
| 1528 const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag; | 1479 const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag; |
| 1529 Comment("[ CopyFixedArrayElements"); | 1480 Comment("[ CopyFixedArrayElements"); |
| 1530 | 1481 |
| (...skipping 1761 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3292 var_entry->Bind(entry); | 3243 var_entry->Bind(entry); |
| 3293 Goto(&loop); | 3244 Goto(&loop); |
| 3294 } | 3245 } |
| 3295 } | 3246 } |
| 3296 | 3247 |
| 3297 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, | 3248 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, |
| 3298 Node* descriptors, Node* nof, | 3249 Node* descriptors, Node* nof, |
| 3299 Label* if_found, | 3250 Label* if_found, |
| 3300 Variable* var_name_index, | 3251 Variable* var_name_index, |
| 3301 Label* if_not_found) { | 3252 Label* if_not_found) { |
| 3302 Variable var_descriptor(this, MachineType::PointerRepresentation()); | 3253 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); |
| 3303 Label loop(this, &var_descriptor); | 3254 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); |
| 3304 var_descriptor.Bind(IntPtrConstant(0)); | 3255 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); |
| 3305 Goto(&loop); | |
| 3306 | 3256 |
| 3307 Bind(&loop); | 3257 BuildFastLoop( |
| 3308 { | 3258 MachineType::PointerRepresentation(), last_exclusive, first_inclusive, |
| 3309 Node* index = var_descriptor.value(); | 3259 [descriptors, unique_name, if_found, var_name_index]( |
| 3310 Node* name_offset = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); | 3260 CodeStubAssembler* assembler, Node* name_index) { |
| 3311 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); | 3261 Node* candidate_name = assembler->LoadFixedArrayElement( |
| 3312 GotoIf(WordEqual(index, nof), if_not_found); | 3262 descriptors, name_index, 0, INTPTR_PARAMETERS); |
| 3313 Node* name_index = IntPtrAdd(name_offset, IntPtrMul(index, factor)); | 3263 var_name_index->Bind(name_index); |
| 3314 Node* candidate_name = | 3264 assembler->GotoIf(assembler->WordEqual(candidate_name, unique_name), |
| 3315 LoadFixedArrayElement(descriptors, name_index, 0, INTPTR_PARAMETERS); | 3265 if_found); |
| 3316 var_name_index->Bind(name_index); | 3266 }, |
| 3317 GotoIf(WordEqual(candidate_name, unique_name), if_found); | 3267 -DescriptorArray::kDescriptorSize, IndexAdvanceMode::kPre); |
| 3318 var_descriptor.Bind(IntPtrAdd(index, IntPtrConstant(1))); | 3268 Goto(if_not_found); |
| 3319 Goto(&loop); | |
| 3320 } | |
| 3321 } | 3269 } |
| 3322 | 3270 |
| 3323 void CodeStubAssembler::TryLookupProperty( | 3271 void CodeStubAssembler::TryLookupProperty( |
| 3324 Node* object, Node* map, Node* instance_type, Node* unique_name, | 3272 Node* object, Node* map, Node* instance_type, Node* unique_name, |
| 3325 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, | 3273 Label* if_found_fast, Label* if_found_dict, Label* if_found_global, |
| 3326 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, | 3274 Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found, |
| 3327 Label* if_bailout) { | 3275 Label* if_bailout) { |
| 3328 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); | 3276 DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep()); |
| 3329 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); | 3277 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); |
| 3330 | 3278 |
| (...skipping 2362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5693 StoreObjectField(cell, WeakCell::kValueOffset, value); | 5641 StoreObjectField(cell, WeakCell::kValueOffset, value); |
| 5694 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, | 5642 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, |
| 5695 Heap::kTheHoleValueRootIndex); | 5643 Heap::kTheHoleValueRootIndex); |
| 5696 | 5644 |
| 5697 // Store the WeakCell in the feedback vector. | 5645 // Store the WeakCell in the feedback vector. |
| 5698 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5646 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
| 5699 CodeStubAssembler::SMI_PARAMETERS); | 5647 CodeStubAssembler::SMI_PARAMETERS); |
| 5700 return cell; | 5648 return cell; |
| 5701 } | 5649 } |
| 5702 | 5650 |
| 5651 void CodeStubAssembler::BuildFastLoop( | |
| 5652 MachineRepresentation index_rep, Node* start_index, Node* end_index, | |
| 5653 std::function<void(CodeStubAssembler* assembler, Node* index)> body, | |
| 5654 int increment, IndexAdvanceMode mode) { | |
| 5655 Variable var(this, index_rep); | |
| 5656 var.Bind(start_index); | |
| 5657 Label loop(this, &var); | |
| 5658 Label after_loop(this); | |
| 5659 BranchIf(WordEqual(var.value(), end_index), &after_loop, &loop); | |
| 5660 Bind(&loop); | |
| 5661 { | |
|
Igor Sheludko
2016/10/04 09:32:25
Why not just put
GotoIf(WordEqual(var.value(),
danno
2016/10/04 16:10:23
As discussed offline, for efficiency. Comment adde
| |
| 5662 if (mode == IndexAdvanceMode::kPre) { | |
| 5663 var.Bind(IntPtrAdd(var.value(), IntPtrConstant(increment))); | |
| 5664 } | |
| 5665 body(this, var.value()); | |
| 5666 if (mode == IndexAdvanceMode::kPost) { | |
| 5667 var.Bind(IntPtrAdd(var.value(), IntPtrConstant(increment))); | |
| 5668 } | |
| 5669 BranchIf(WordNotEqual(var.value(), end_index), &loop, &after_loop); | |
| 5670 } | |
| 5671 Bind(&after_loop); | |
| 5672 } | |
| 5673 | |
| 5674 void CodeStubAssembler::BuildFastFixedArrayForEach( | |
| 5675 compiler::Node* fixed_array, ElementsKind kind, | |
| 5676 compiler::Node* first_element_inclusive, | |
| 5677 compiler::Node* last_element_exclusive, | |
| 5678 std::function<void(CodeStubAssembler* assembler, | |
| 5679 compiler::Node* fixed_array, compiler::Node* offset)> | |
| 5680 body, | |
| 5681 ParameterMode mode, ForEachDirection direction) { | |
|
Igor Sheludko
2016/10/04 09:32:25
I think we should put this assert somewhere in thi
danno
2016/10/04 16:10:23
Done.
| |
| 5682 int32_t first_val; | |
| 5683 bool constant_first = ToInt32Constant(first_element_inclusive, first_val); | |
| 5684 int32_t last_val; | |
| 5685 bool constent_last = ToInt32Constant(last_element_exclusive, last_val); | |
| 5686 if (constant_first && constent_last) { | |
| 5687 int delta = last_val - first_val; | |
| 5688 DCHECK(delta >= 0); | |
| 5689 if (delta <= kElementLoopUnrollThreshold) { | |
| 5690 if (direction == ForEachDirection::kForward) { | |
| 5691 for (int i = first_val; i < last_val; ++i) { | |
| 5692 Node* index = IntPtrConstant(i); | |
| 5693 Node* offset = | |
| 5694 ElementOffsetFromIndex(index, FAST_ELEMENTS, mode, | |
|
Igor Sheludko
2016/10/04 09:32:25
I think you intended to use |kind| instead of |FAS
danno
2016/10/04 16:10:23
Done.
| |
| 5695 FixedArray::kHeaderSize - kHeapObjectTag); | |
| 5696 body(this, fixed_array, offset); | |
| 5697 } | |
| 5698 } else { | |
| 5699 for (int i = last_val - 1; i >= first_val; --i) { | |
| 5700 Node* index = IntPtrConstant(i); | |
| 5701 Node* offset = | |
| 5702 ElementOffsetFromIndex(index, FAST_ELEMENTS, mode, | |
|
Igor Sheludko
2016/10/04 09:32:25
Same here
danno
2016/10/04 16:10:23
Done.
| |
| 5703 FixedArray::kHeaderSize - kHeapObjectTag); | |
| 5704 body(this, fixed_array, offset); | |
| 5705 } | |
| 5706 } | |
| 5707 return; | |
| 5708 } | |
| 5709 } | |
| 5710 | |
| 5711 Node* start = | |
| 5712 ElementOffsetFromIndex(first_element_inclusive, kind, mode, | |
| 5713 FixedArray::kHeaderSize - kHeapObjectTag); | |
| 5714 Node* limit = | |
| 5715 ElementOffsetFromIndex(last_element_exclusive, kind, mode, | |
| 5716 FixedArray::kHeaderSize - kHeapObjectTag); | |
| 5717 if (direction == ForEachDirection::kReverse) std::swap(start, limit); | |
| 5718 | |
| 5719 int increment = IsFastDoubleElementsKind(kind) ? kDoubleSize : kPointerSize; | |
| 5720 BuildFastLoop( | |
| 5721 MachineType::PointerRepresentation(), start, limit, | |
| 5722 [fixed_array, body](CodeStubAssembler* assembler, Node* index) { | |
|
Igor Sheludko
2016/10/04 09:32:25
s/index/offset/
danno
2016/10/04 16:10:23
Done.
| |
| 5723 body(assembler, fixed_array, index); | |
| 5724 }, | |
| 5725 direction == ForEachDirection::kReverse ? -increment : increment, | |
| 5726 direction == ForEachDirection::kReverse ? IndexAdvanceMode::kPre | |
| 5727 : IndexAdvanceMode::kPost); | |
| 5728 } | |
| 5729 | |
| 5703 } // namespace internal | 5730 } // namespace internal |
| 5704 } // namespace v8 | 5731 } // namespace v8 |
| OLD | NEW |