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 4525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4536 // Get the map entry from the cache. | 4536 // Get the map entry from the cache. |
4537 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - | 4537 DCHECK_EQ(kPointerSize * 2, stub_cache->map_reference(table).address() - |
4538 stub_cache->key_reference(table).address()); | 4538 stub_cache->key_reference(table).address()); |
4539 Node* entry_map = | 4539 Node* entry_map = |
4540 Load(MachineType::Pointer(), key_base, | 4540 Load(MachineType::Pointer(), key_base, |
4541 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); | 4541 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize * 2))); |
4542 GotoIf(WordNotEqual(map, entry_map), if_miss); | 4542 GotoIf(WordNotEqual(map, entry_map), if_miss); |
4543 | 4543 |
4544 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - | 4544 DCHECK_EQ(kPointerSize, stub_cache->value_reference(table).address() - |
4545 stub_cache->key_reference(table).address()); | 4545 stub_cache->key_reference(table).address()); |
4546 Node* code = Load(MachineType::Pointer(), key_base, | 4546 Node* handler = Load(MachineType::Pointer(), key_base, |
4547 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); | 4547 IntPtrAdd(entry_offset, IntPtrConstant(kPointerSize))); |
4548 | 4548 |
4549 // We found the handler. | 4549 // We found the handler. |
4550 var_handler->Bind(code); | 4550 var_handler->Bind(handler); |
4551 Goto(if_handler); | 4551 Goto(if_handler); |
4552 } | 4552 } |
4553 | 4553 |
4554 void CodeStubAssembler::TryProbeStubCache( | 4554 void CodeStubAssembler::TryProbeStubCache( |
4555 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, | 4555 StubCache* stub_cache, compiler::Node* receiver, compiler::Node* name, |
4556 Label* if_handler, Variable* var_handler, Label* if_miss) { | 4556 Label* if_handler, Variable* var_handler, Label* if_miss) { |
4557 Label try_secondary(this), miss(this); | 4557 Label try_secondary(this), miss(this); |
4558 | 4558 |
4559 Counters* counters = isolate()->counters(); | 4559 Counters* counters = isolate()->counters(); |
4560 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 4560 IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4826 var_double_value->Bind(element); | 4826 var_double_value->Bind(element); |
4827 Goto(rebox_double); | 4827 Goto(rebox_double); |
4828 } | 4828 } |
4829 } | 4829 } |
4830 } | 4830 } |
4831 | 4831 |
4832 void CodeStubAssembler::HandleLoadICHandlerCase( | 4832 void CodeStubAssembler::HandleLoadICHandlerCase( |
4833 const LoadICParameters* p, Node* handler, Label* miss, | 4833 const LoadICParameters* p, Node* handler, Label* miss, |
4834 ElementSupport support_elements) { | 4834 ElementSupport support_elements) { |
4835 Comment("have_handler"); | 4835 Comment("have_handler"); |
4836 Label call_handler(this); | 4836 Variable var_holder(this, MachineRepresentation::kTagged); |
4837 GotoUnless(TaggedIsSmi(handler), &call_handler); | 4837 var_holder.Bind(p->receiver); |
| 4838 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 4839 var_smi_handler.Bind(handler); |
| 4840 |
| 4841 Variable* vars[] = {&var_holder, &var_smi_handler}; |
| 4842 Label if_smi_handler(this, 2, vars); |
| 4843 Label try_proto_cell_handler(this), call_handler(this); |
| 4844 |
| 4845 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_cell_handler); |
4838 | 4846 |
4839 // |handler| is a Smi, encoding what to do. See handler-configuration.h | 4847 // |handler| is a Smi, encoding what to do. See handler-configuration.h |
4840 // for the encoding format. | 4848 // for the encoding format. |
| 4849 Bind(&if_smi_handler); |
4841 { | 4850 { |
4842 Variable var_double_value(this, MachineRepresentation::kFloat64); | 4851 Variable var_double_value(this, MachineRepresentation::kFloat64); |
4843 Label rebox_double(this, &var_double_value); | 4852 Label rebox_double(this, &var_double_value); |
4844 | 4853 |
4845 Node* handler_word = SmiUntag(handler); | 4854 Node* holder = var_holder.value(); |
| 4855 Node* handler_word = SmiUntag(var_smi_handler.value()); |
4846 if (support_elements == kSupportElements) { | 4856 if (support_elements == kSupportElements) { |
4847 Label property(this); | 4857 Label property(this); |
4848 Node* handler_type = | 4858 Node* handler_type = |
4849 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); | 4859 WordAnd(handler_word, IntPtrConstant(LoadHandlerTypeBit::kMask)); |
4850 GotoUnless( | 4860 GotoUnless( |
4851 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), | 4861 WordEqual(handler_type, IntPtrConstant(kLoadICHandlerForElements)), |
4852 &property); | 4862 &property); |
4853 | 4863 |
4854 Comment("element_load"); | 4864 Comment("element_load"); |
4855 Node* intptr_index = TryToIntptr(p->name, miss); | 4865 Node* intptr_index = TryToIntptr(p->name, miss); |
4856 Node* elements = LoadElements(p->receiver); | 4866 Node* elements = LoadElements(holder); |
4857 Node* is_jsarray = | 4867 Node* is_jsarray = |
4858 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); | 4868 WordAnd(handler_word, IntPtrConstant(KeyedLoadIsJsArray::kMask)); |
4859 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); | 4869 Node* is_jsarray_condition = WordNotEqual(is_jsarray, IntPtrConstant(0)); |
4860 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); | 4870 Node* elements_kind = BitFieldDecode<KeyedLoadElementsKind>(handler_word); |
4861 Label if_hole(this), unimplemented_elements_kind(this); | 4871 Label if_hole(this), unimplemented_elements_kind(this); |
4862 Label* out_of_bounds = miss; | 4872 Label* out_of_bounds = miss; |
4863 EmitElementLoad(p->receiver, elements, elements_kind, intptr_index, | 4873 EmitElementLoad(holder, elements, elements_kind, intptr_index, |
4864 is_jsarray_condition, &if_hole, &rebox_double, | 4874 is_jsarray_condition, &if_hole, &rebox_double, |
4865 &var_double_value, &unimplemented_elements_kind, | 4875 &var_double_value, &unimplemented_elements_kind, |
4866 out_of_bounds, miss); | 4876 out_of_bounds, miss); |
4867 | 4877 |
4868 Bind(&unimplemented_elements_kind); | 4878 Bind(&unimplemented_elements_kind); |
4869 { | 4879 { |
4870 // Smi handlers should only be installed for supported elements kinds. | 4880 // Smi handlers should only be installed for supported elements kinds. |
4871 // Crash if we get here. | 4881 // Crash if we get here. |
4872 DebugBreak(); | 4882 DebugBreak(); |
4873 Goto(miss); | 4883 Goto(miss); |
(...skipping 26 matching lines...) Expand all Loading... |
4900 Node* inobject_bit = | 4910 Node* inobject_bit = |
4901 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); | 4911 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsInobject::kMask)); |
4902 Node* double_bit = | 4912 Node* double_bit = |
4903 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); | 4913 WordAnd(handler_word, IntPtrConstant(FieldOffsetIsDouble::kMask)); |
4904 Node* offset = | 4914 Node* offset = |
4905 WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); | 4915 WordSar(handler_word, IntPtrConstant(FieldOffsetOffset::kShift)); |
4906 | 4916 |
4907 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); | 4917 GotoIf(WordEqual(inobject_bit, IntPtrConstant(0)), &out_of_object); |
4908 | 4918 |
4909 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); | 4919 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &inobject_double); |
4910 Return(LoadObjectField(p->receiver, offset)); | 4920 Return(LoadObjectField(holder, offset)); |
4911 | 4921 |
4912 Bind(&inobject_double); | 4922 Bind(&inobject_double); |
4913 if (FLAG_unbox_double_fields) { | 4923 if (FLAG_unbox_double_fields) { |
4914 var_double_value.Bind( | 4924 var_double_value.Bind( |
4915 LoadObjectField(p->receiver, offset, MachineType::Float64())); | 4925 LoadObjectField(holder, offset, MachineType::Float64())); |
4916 } else { | 4926 } else { |
4917 Node* mutable_heap_number = LoadObjectField(p->receiver, offset); | 4927 Node* mutable_heap_number = LoadObjectField(holder, offset); |
4918 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); | 4928 var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number)); |
4919 } | 4929 } |
4920 Goto(&rebox_double); | 4930 Goto(&rebox_double); |
4921 | 4931 |
4922 Bind(&out_of_object); | 4932 Bind(&out_of_object); |
4923 Node* properties = LoadProperties(p->receiver); | 4933 Node* properties = LoadProperties(holder); |
4924 Node* value = LoadObjectField(properties, offset); | 4934 Node* value = LoadObjectField(properties, offset); |
4925 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); | 4935 GotoUnless(WordEqual(double_bit, IntPtrConstant(0)), &out_of_object_double); |
4926 Return(value); | 4936 Return(value); |
4927 | 4937 |
4928 Bind(&out_of_object_double); | 4938 Bind(&out_of_object_double); |
4929 var_double_value.Bind(LoadHeapNumberValue(value)); | 4939 var_double_value.Bind(LoadHeapNumberValue(value)); |
4930 Goto(&rebox_double); | 4940 Goto(&rebox_double); |
4931 | 4941 |
4932 Bind(&rebox_double); | 4942 Bind(&rebox_double); |
4933 Return(AllocateHeapNumberWithValue(var_double_value.value())); | 4943 Return(AllocateHeapNumberWithValue(var_double_value.value())); |
4934 } | 4944 } |
4935 | 4945 |
| 4946 Bind(&try_proto_cell_handler); |
| 4947 { |
| 4948 GotoIf(WordNotEqual(LoadMap(handler), LoadRoot(Heap::kTuple3MapRootIndex)), |
| 4949 &call_handler); |
| 4950 Node* validity_cell = LoadObjectField(handler, Tuple3::kValue1Offset); |
| 4951 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
| 4952 GotoIf(WordNotEqual(cell_value, |
| 4953 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), |
| 4954 miss); |
| 4955 |
| 4956 Node* holder = |
| 4957 LoadWeakCellValue(LoadObjectField(handler, Tuple3::kValue2Offset)); |
| 4958 // The |holder| is guaranteed to be alive at this point since we passed |
| 4959 // both the receiver map check and the validity cell check. |
| 4960 Assert(WordNotEqual(holder, IntPtrConstant(0))); |
| 4961 |
| 4962 Node* smi_handler = LoadObjectField(handler, Tuple3::kValue3Offset); |
| 4963 Assert(TaggedIsSmi(smi_handler)); |
| 4964 |
| 4965 var_holder.Bind(holder); |
| 4966 var_smi_handler.Bind(smi_handler); |
| 4967 Goto(&if_smi_handler); |
| 4968 } |
| 4969 |
4936 // |handler| is a heap object. Must be code, call it. | 4970 // |handler| is a heap object. Must be code, call it. |
4937 Bind(&call_handler); | 4971 Bind(&call_handler); |
4938 typedef LoadWithVectorDescriptor Descriptor; | 4972 { |
4939 TailCallStub(Descriptor(isolate()), handler, p->context, | 4973 typedef LoadWithVectorDescriptor Descriptor; |
4940 Arg(Descriptor::kReceiver, p->receiver), | 4974 TailCallStub(Descriptor(isolate()), handler, p->context, |
4941 Arg(Descriptor::kName, p->name), | 4975 Arg(Descriptor::kReceiver, p->receiver), |
4942 Arg(Descriptor::kSlot, p->slot), | 4976 Arg(Descriptor::kName, p->name), |
4943 Arg(Descriptor::kVector, p->vector)); | 4977 Arg(Descriptor::kSlot, p->slot), |
| 4978 Arg(Descriptor::kVector, p->vector)); |
| 4979 } |
4944 } | 4980 } |
4945 | 4981 |
4946 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { | 4982 void CodeStubAssembler::LoadIC(const LoadICParameters* p) { |
4947 Variable var_handler(this, MachineRepresentation::kTagged); | 4983 Variable var_handler(this, MachineRepresentation::kTagged); |
4948 // TODO(ishell): defer blocks when it works. | 4984 // TODO(ishell): defer blocks when it works. |
4949 Label if_handler(this, &var_handler), try_polymorphic(this), | 4985 Label if_handler(this, &var_handler), try_polymorphic(this), |
4950 try_megamorphic(this /*, Label::kDeferred*/), | 4986 try_megamorphic(this /*, Label::kDeferred*/), |
4951 miss(this /*, Label::kDeferred*/); | 4987 miss(this /*, Label::kDeferred*/); |
4952 | 4988 |
4953 Node* receiver_map = LoadReceiverMap(p->receiver); | 4989 Node* receiver_map = LoadReceiverMap(p->receiver); |
(...skipping 2462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7416 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); | 7452 result.Bind(CallRuntime(Runtime::kInstanceOf, context, object, callable)); |
7417 Goto(&end); | 7453 Goto(&end); |
7418 } | 7454 } |
7419 | 7455 |
7420 Bind(&end); | 7456 Bind(&end); |
7421 return result.value(); | 7457 return result.value(); |
7422 } | 7458 } |
7423 | 7459 |
7424 } // namespace internal | 7460 } // namespace internal |
7425 } // namespace v8 | 7461 } // namespace v8 |
OLD | NEW |