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 4346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4357 // Get the map entry from the cache. | 4357 // Get the map entry from the cache. |
4358 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - | 4358 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - |
4359 stub_cache->key_reference(table).address()); | 4359 stub_cache->key_reference(table).address()); |
4360 Node* entry_map = | 4360 Node* entry_map = |
4361 Load(MachineType::Pointer(), key_base, | 4361 Load(MachineType::Pointer(), key_base, |
4362 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); | 4362 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); |
4363 GotoIf(WordNotEqual(map, entry_map), if_miss); | 4363 GotoIf(WordNotEqual(map, entry_map), if_miss); |
4364 | 4364 |
4365 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - | 4365 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - |
4366 stub_cache->key_reference(table).address()); | 4366 stub_cache->key_reference(table).address()); |
4367 Node* code = Load(MachineType::Pointer(), key_base, | 4367 Node* handler = Load(MachineType::Pointer(), key_base, |
4368 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); | 4368 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
4369 | 4369 |
4370 // We found the handler. | 4370 // We found the handler. |
4371 var_handler->Bind(code); | 4371 var_handler->Bind(handler); |
4372 Goto(if_handler); | 4372 Goto(if_handler); |
4373 } | 4373 } |
4374 | 4374 |
4375 void CodeStubAssembler::TryProbeStubCache( | 4375 void CodeStubAssembler::TryProbeStubCache( |
4376 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, | 4376 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, |
4377 Label* if_handler, Variable* var_handler, Label* if_miss) { | 4377 Label* if_handler, Variable* var_handler, Label* if_miss) { |
4378 Label try_secondary(this), miss(this); | 4378 Label try_secondary(this), miss(this); |
4379 | 4379 |
4380 Counters* counters = isolate()->counters(); | 4380 Counters* counters = isolate()->counters(); |
4381 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 4381 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4647 var_double_value->Bind(element); | 4647 var_double_value->Bind(element); |
4648 Goto(rebox_double); | 4648 Goto(rebox_double); |
4649 } | 4649 } |
4650 } | 4650 } |
4651 } | 4651 } |
4652 | 4652 |
4653 void CodeStubAssembler::HandleLoadICHandlerCase( | 4653 void CodeStubAssembler::HandleLoadICHandlerCase( |
4654 const LoadICParameters* p, Node* handler, Label* miss, | 4654 const LoadICParameters* p, Node* handler, Label* miss, |
4655 ElementSupport support_elements) { | 4655 ElementSupport support_elements) { |
4656 Comment("have_handler"); | 4656 Comment("have_handler"); |
4657 Label call_handler(this); | 4657 Variable var_holder(this, MachineRepresentation::kTagged); |
4658 GotoUnless(TaggedIsSmi(handler), &call_handler); | 4658 var_holder.Bind(p->receiver); |
4659 Variable var_handler(this, MachineRepresentation::kTagged); | |
4660 var_handler.Bind(handler); | |
4661 | |
4662 Variable* vars[] = {&var_holder, &var_handler}; | |
4663 Label if_smi_handler(this, 2, vars); | |
4664 Label try_proto_cell_handler(this), call_handler(this); | |
4665 | |
4666 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_cell_handler); | |
4659 | 4667 |
4660 // |handler| is a Smi, encoding what to do. See handler-configuration.h | 4668 // |handler| is a Smi, encoding what to do. See handler-configuration.h |
4661 // for the encoding format. | 4669 // for the encoding format. |
4670 Bind(&if_smi_handler); | |
4662 { | 4671 { |
4672 Node* holder = var_holder.value(); | |
4673 Node* handler = var_handler.value(); | |
Jakob Kummerow
2016/10/13 11:59:26
nit: This (and its two friends in 4770 and 4794) s
Igor Sheludko
2016/10/13 13:20:38
Done.
| |
4663 Variable var_double_value(this, MachineRepresentation::kFloat64); | 4674 Variable var_double_value(this, MachineRepresentation::kFloat64); |
4664 Label rebox_double(this, &var_double_value); | 4675 Label rebox_double(this, &var_double_value); |
4665 | 4676 |
4666 Node* handler_word = SmiUntag(handler); | 4677 Node* handler_word = SmiUntag(handler); |
4667 if (support_elements == kSupportElements) { | 4678 if (support_elements == kSupportElements) { |
4668 Label property(this); | 4679 Label property(this); |
4669 Node* handler_type = | 4680 Node* handler_type = |
4670 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); | 4681 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); |
4671 GotoUnless( | 4682 GotoUnless( |
4672 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), | 4683 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), |
4673 &property); | 4684 &property); |
4674 | 4685 |
4675 Comment("element_load"); | 4686 Comment("element_load"); |
4676 Node* intptr_index = TryToIntptr(p->name, miss); | 4687 Node* intptr_index = TryToIntptr(p->name, miss); |
4677 Node* elements = LoadElements(p->receiver); | 4688 Node* elements = LoadElements(holder); |
4678 Node* is_jsarray = | 4689 Node* is_jsarray = |
4679 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); | 4690 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); |
4680 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); | 4691 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); |
4681 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); | 4692 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); |
4682 Label if_hole(this), unimplemented_elements_kind(this); | 4693 Label if_hole(this), unimplemented_elements_kind(this); |
4683 Label* out_of_bounds = miss; | 4694 Label* out_of_bounds = miss; |
4684 EmitElementLoad(p->receiver, elements, elements_kind, intptr_index, | 4695 EmitElementLoad(holder, elements, elements_kind, intptr_index, |
4685 is_jsarray_condition, &if_hole, &rebox_double, | 4696 is_jsarray_condition, &if_hole, &rebox_double, |
4686 &var_double_value, &unimplemented_elements_kind, | 4697 &var_double_value, &unimplemented_elements_kind, |
4687 out_of_bounds, miss); | 4698 out_of_bounds, miss); |
4688 | 4699 |
4689 Bind(&unimplemented_elements_kind); | 4700 Bind(&unimplemented_elements_kind); |
4690 { | 4701 { |
4691 // Smi handlers should only be installed for supported elements kinds. | 4702 // Smi handlers should only be installed for supported elements kinds. |
4692 // Crash if we get here. | 4703 // Crash if we get here. |
4693 DebugBreak(); | 4704 DebugBreak(); |
4694 Goto(miss); | 4705 Goto(miss); |
(...skipping 26 matching lines...) Expand all Loading... | |
4721 Node* inobject_bit = | 4732 Node* inobject_bit = |
4722 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); | 4733 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); |
4723 Node* double_bit = | 4734 Node* double_bit = |
4724 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); | 4735 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); |
4725 Node* offset = | 4736 Node* offset = |
4726 WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); | 4737 WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); |
4727 | 4738 |
4728 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); | 4739 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); |
4729 | 4740 |
4730 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); | 4741 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); |
4731 Return(LoadObjectField(p->receiver, offset)); | 4742 Return(LoadObjectField(holder, offset)); |
4732 | 4743 |
4733 Bind(&inobject_double); | 4744 Bind(&inobject_double); |
4734 if (FLAG_unbox_double_fields) { | 4745 if (FLAG_unbox_double_fields) { |
4735 var_double_value.Bind( | 4746 var_double_value.Bind( |
4736 LoadObjectField(p->receiver, offset, MachineType::Float64())); | 4747 LoadObjectField(holder, offset, MachineType::Float64())); |
4737 } else { | 4748 } else { |
4738 Node* mutable_heap_number = LoadObjectField(p->receiver, offset); | 4749 Node* mutable_heap_number = LoadObjectField(holder, offset); |
4739 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | 4750 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
4740 } | 4751 } |
4741 Goto(&rebox_double); | 4752 Goto(&rebox_double); |
4742 | 4753 |
4743 Bind(&out_of_object); | 4754 Bind(&out_of_object); |
4744 Node* properties = LoadProperties(p->receiver); | 4755 Node* properties = LoadProperties(holder); |
4745 Node* value = LoadObjectField(properties, offset); | 4756 Node* value = LoadObjectField(properties, offset); |
4746 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); | 4757 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); |
4747 Return(value); | 4758 Return(value); |
4748 | 4759 |
4749 Bind(&out_of_object_double); | 4760 Bind(&out_of_object_double); |
4750 var_double_value.Bind(LoadHeapNumberValue(value)); | 4761 var_double_value.Bind(LoadHeapNumberValue(value)); |
4751 Goto(&rebox_double); | 4762 Goto(&rebox_double); |
4752 | 4763 |
4753 Bind(&rebox_double); | 4764 Bind(&rebox_double); |
4754 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 4765 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
4755 } | 4766 } |
4756 | 4767 |
4768 Bind(&try_proto_cell_handler); | |
4769 { | |
4770 Node* handler = var_handler.value(); | |
4771 GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), | |
4772 &call_handler); | |
4773 Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); | |
4774 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | |
4775 GotoIf(WordNotEqual(cell_value, | |
4776 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | |
4777 miss); | |
4778 | |
4779 Node* holder = | |
4780 LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); | |
4781 Assert(WordNotEqual(holder, IntPtrConstant(0))); | |
Jakob Kummerow
2016/10/13 11:59:26
Why is it guaranteed that this WeakCell has not be
Igor Sheludko
2016/10/13 13:20:38
Done.
| |
4782 | |
4783 Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); | |
4784 Assert(TaggedIsSmi(smi_handler)); | |
4785 | |
4786 var_holder.Bind(holder); | |
4787 var_handler.Bind(smi_handler); | |
4788 Goto(&if_smi_handler); | |
4789 } | |
4790 | |
4757 // |handler| is a heap object. Must be code, call it. | 4791 // |handler| is a heap object. Must be code, call it. |
4758 Bind(&call_handler); | 4792 Bind(&call_handler); |
4759 typedef LoadWithVectorDescriptor Descriptor; | 4793 { |
4760 TailCallStub(Descriptor(isolate()), handler, p->context, | 4794 Node* handler = var_handler.value(); |
4761 Arg(Descriptor::kReceiver, p->receiver), | 4795 typedef LoadWithVectorDescriptor Descriptor; |
4762 Arg(Descriptor::kName, p->name), | 4796 TailCallStub(Descriptor(isolate()), handler, p->context, |
4763 Arg(Descriptor::kSlot, p->slot), | 4797 Arg(Descriptor::kReceiver, p->receiver), |
4764 Arg(Descriptor::kVector, p->vector)); | 4798 Arg(Descriptor::kName, p->name), |
4799 Arg(Descriptor::kSlot, p->slot), | |
4800 Arg(Descriptor::kVector, p->vector)); | |
4801 } | |
4765 } | 4802 } |
4766 | 4803 |
4767 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 4804 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
4768 Variable var_handler(this, MachineRepresentation::kTagged); | 4805 Variable var_handler(this, MachineRepresentation::kTagged); |
4769 // TODO(ishell): defer blocks when it works. | 4806 // TODO(ishell): defer blocks when it works. |
4770 Label if_handler(this, &var_handler), try_polymorphic(this), | 4807 Label if_handler(this, &var_handler), try_polymorphic(this), |
4771 try_megamorphic(this /*, Label::kDeferred*/), | 4808 try_megamorphic(this /*, Label::kDeferred*/), |
4772 miss(this /*, Label::kDeferred*/); | 4809 miss(this /*, Label::kDeferred*/); |
4773 | 4810 |
4774 Node* receiver_map = LoadReceiverMap(p->receiver); | 4811 Node* receiver_map = LoadReceiverMap(p->receiver); |
(...skipping 2462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7237 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); | 7274 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); |
7238 Goto(&end); | 7275 Goto(&end); |
7239 } | 7276 } |
7240 | 7277 |
7241 Bind(&end); | 7278 Bind(&end); |
7242 return result.value(); | 7279 return result.value(); |
7243 } | 7280 } |
7244 | 7281 |
7245 } // namespace internal | 7282 } // namespace internal |
7246 } // namespace v8 | 7283 } // namespace v8 |
OLD | NEW |