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