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