Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: src/code-stub-assembler.cc

Issue 2419513002: [ic] Support data handlers that represent loads from prototypes. (Closed)
Patch Set: Rebasing Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ast/ast-types.cc ('k') | src/compiler/types.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/ast/ast-types.cc ('k') | src/compiler/types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698