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 4432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4443 TailCallStub(descriptor, handler, p->context, receiver, fake_name, p->slot, | 4443 TailCallStub(descriptor, handler, p->context, receiver, fake_name, p->slot, |
4444 p->vector); | 4444 p->vector); |
4445 } | 4445 } |
4446 Bind(&miss); | 4446 Bind(&miss); |
4447 { | 4447 { |
4448 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->slot, | 4448 TailCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, p->slot, |
4449 p->vector); | 4449 p->vector); |
4450 } | 4450 } |
4451 } | 4451 } |
4452 | 4452 |
| 4453 void CodeStubAssembler::ExtendPropertiesBackingStore(compiler::Node* object) { |
| 4454 Node* properties = LoadProperties(object); |
| 4455 Node* length = LoadFixedArrayBaseLength(properties); |
| 4456 |
| 4457 ParameterMode mode = OptimalParameterMode(); |
| 4458 length = UntagParameter(length, mode); |
| 4459 |
| 4460 Node* delta = IntPtrOrSmiConstant(JSObject::kFieldsAdded, mode); |
| 4461 Node* new_capacity = IntPtrAdd(length, delta); |
| 4462 |
| 4463 // Grow properties array. |
| 4464 ElementsKind kind = FAST_ELEMENTS; |
| 4465 DCHECK(kMaxNumberOfDescriptors + JSObject::kFieldsAdded < |
| 4466 FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind)); |
| 4467 // The size of a new properties backing store is guaranteed to be small |
| 4468 // enough that the new backing store will be allocated in new space. |
| 4469 Assert(UintPtrLessThan(new_capacity, IntPtrConstant(kMaxNumberOfDescriptors + |
| 4470 JSObject::kFieldsAdded))); |
| 4471 |
| 4472 Node* new_properties = AllocateFixedArray(kind, new_capacity, mode); |
| 4473 |
| 4474 FillFixedArrayWithValue(kind, new_properties, length, new_capacity, |
| 4475 Heap::kUndefinedValueRootIndex, mode); |
| 4476 |
| 4477 // |new_properties| is guaranteed to be in new space, so we can skip |
| 4478 // the write barrier. |
| 4479 CopyFixedArrayElements(kind, properties, new_properties, length, |
| 4480 SKIP_WRITE_BARRIER, mode); |
| 4481 |
| 4482 StoreObjectField(object, JSObject::kPropertiesOffset, new_properties); |
| 4483 } |
| 4484 |
4453 Node* CodeStubAssembler::PrepareValueForWrite(Node* value, | 4485 Node* CodeStubAssembler::PrepareValueForWrite(Node* value, |
4454 Representation representation, | 4486 Representation representation, |
4455 Label* bailout) { | 4487 Label* bailout) { |
4456 if (representation.IsDouble()) { | 4488 if (representation.IsDouble()) { |
4457 Variable var_value(this, MachineRepresentation::kFloat64); | 4489 Variable var_value(this, MachineRepresentation::kFloat64); |
4458 Label if_smi(this), if_heap_object(this), done(this); | 4490 Label if_smi(this), if_heap_object(this), done(this); |
4459 Branch(WordIsSmi(value), &if_smi, &if_heap_object); | 4491 Branch(WordIsSmi(value), &if_smi, &if_heap_object); |
4460 Bind(&if_smi); | 4492 Bind(&if_smi); |
4461 { | 4493 { |
4462 var_value.Bind(SmiToFloat64(value)); | 4494 var_value.Bind(SmiToFloat64(value)); |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4875 length, capacity, mode, bailout); | 4907 length, capacity, mode, bailout); |
4876 | 4908 |
4877 new_elements_var.Bind(new_elements); | 4909 new_elements_var.Bind(new_elements); |
4878 Goto(&done); | 4910 Goto(&done); |
4879 } | 4911 } |
4880 | 4912 |
4881 Bind(&done); | 4913 Bind(&done); |
4882 return new_elements_var.value(); | 4914 return new_elements_var.value(); |
4883 } | 4915 } |
4884 | 4916 |
| 4917 void CodeStubAssembler::TransitionElementsKind( |
| 4918 compiler::Node* object, compiler::Node* map, ElementsKind from_kind, |
| 4919 ElementsKind to_kind, bool is_jsarray, Label* bailout) { |
| 4920 DCHECK(!IsFastHoleyElementsKind(from_kind) || |
| 4921 IsFastHoleyElementsKind(to_kind)); |
| 4922 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) { |
| 4923 TrapAllocationMemento(object, bailout); |
| 4924 } |
| 4925 |
| 4926 if (!IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4927 Comment("Non-simple map transition"); |
| 4928 Node* elements = LoadElements(object); |
| 4929 |
| 4930 Node* empty_fixed_array = |
| 4931 HeapConstant(isolate()->factory()->empty_fixed_array()); |
| 4932 |
| 4933 Label done(this); |
| 4934 GotoIf(WordEqual(elements, empty_fixed_array), &done); |
| 4935 |
| 4936 // TODO(ishell): Use OptimalParameterMode(). |
| 4937 ParameterMode mode = INTPTR_PARAMETERS; |
| 4938 Node* elements_length = SmiUntag(LoadFixedArrayBaseLength(elements)); |
| 4939 Node* array_length = |
| 4940 is_jsarray ? SmiUntag(LoadObjectField(object, JSArray::kLengthOffset)) |
| 4941 : elements_length; |
| 4942 |
| 4943 GrowElementsCapacity(object, elements, from_kind, to_kind, array_length, |
| 4944 elements_length, mode, bailout); |
| 4945 Goto(&done); |
| 4946 Bind(&done); |
| 4947 } |
| 4948 |
| 4949 StoreObjectField(object, JSObject::kMapOffset, map); |
| 4950 } |
| 4951 |
| 4952 void CodeStubAssembler::TrapAllocationMemento(Node* object, |
| 4953 Label* memento_found) { |
| 4954 Comment("[ TrapAllocationMemento"); |
| 4955 Label no_memento_found(this); |
| 4956 Label top_check(this), map_check(this); |
| 4957 |
| 4958 Node* new_space_top_address = ExternalConstant( |
| 4959 ExternalReference::new_space_allocation_top_address(isolate())); |
| 4960 const int kMementoMapOffset = JSArray::kSize - kHeapObjectTag; |
| 4961 const int kMementoEndOffset = kMementoMapOffset + AllocationMemento::kSize; |
| 4962 |
| 4963 // Bail out if the object is not in new space. |
| 4964 Node* object_page = PageFromAddress(object); |
| 4965 { |
| 4966 const int mask = |
| 4967 (1 << MemoryChunk::IN_FROM_SPACE) | (1 << MemoryChunk::IN_TO_SPACE); |
| 4968 Node* page_flags = Load(MachineType::IntPtr(), object_page); |
| 4969 GotoIf( |
| 4970 WordEqual(WordAnd(page_flags, IntPtrConstant(mask)), IntPtrConstant(0)), |
| 4971 &no_memento_found); |
| 4972 } |
| 4973 |
| 4974 Node* memento_end = IntPtrAdd(object, IntPtrConstant(kMementoEndOffset)); |
| 4975 Node* memento_end_page = PageFromAddress(memento_end); |
| 4976 |
| 4977 Node* new_space_top = Load(MachineType::Pointer(), new_space_top_address); |
| 4978 Node* new_space_top_page = PageFromAddress(new_space_top); |
| 4979 |
| 4980 // If the object is in new space, we need to check whether it is and |
| 4981 // respective potential memento object on the same page as the current top. |
| 4982 GotoIf(WordEqual(memento_end_page, new_space_top_page), &top_check); |
| 4983 |
| 4984 // The object is on a different page than allocation top. Bail out if the |
| 4985 // object sits on the page boundary as no memento can follow and we cannot |
| 4986 // touch the memory following it. |
| 4987 Branch(WordEqual(object_page, memento_end_page), &map_check, |
| 4988 &no_memento_found); |
| 4989 |
| 4990 // If top is on the same page as the current object, we need to check whether |
| 4991 // we are below top. |
| 4992 Bind(&top_check); |
| 4993 { |
| 4994 Branch(UintPtrGreaterThan(memento_end, new_space_top), &no_memento_found, |
| 4995 &map_check); |
| 4996 } |
| 4997 |
| 4998 // Memento map check. |
| 4999 Bind(&map_check); |
| 5000 { |
| 5001 Node* memento_map = LoadObjectField(object, kMementoMapOffset); |
| 5002 Branch( |
| 5003 WordEqual(memento_map, LoadRoot(Heap::kAllocationMementoMapRootIndex)), |
| 5004 memento_found, &no_memento_found); |
| 5005 } |
| 5006 Bind(&no_memento_found); |
| 5007 Comment("] TrapAllocationMemento"); |
| 5008 } |
| 5009 |
| 5010 Node* CodeStubAssembler::PageFromAddress(Node* address) { |
| 5011 return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask)); |
| 5012 } |
| 5013 |
4885 Node* CodeStubAssembler::EnumLength(Node* map) { | 5014 Node* CodeStubAssembler::EnumLength(Node* map) { |
4886 Node* bitfield_3 = LoadMapBitField3(map); | 5015 Node* bitfield_3 = LoadMapBitField3(map); |
4887 Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3); | 5016 Node* enum_length = BitFieldDecode<Map::EnumLengthBits>(bitfield_3); |
4888 return SmiTag(enum_length); | 5017 return SmiTag(enum_length); |
4889 } | 5018 } |
4890 | 5019 |
4891 void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, | 5020 void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache, |
4892 Label* use_runtime) { | 5021 Label* use_runtime) { |
4893 Variable current_js_object(this, MachineRepresentation::kTagged); | 5022 Variable current_js_object(this, MachineRepresentation::kTagged); |
4894 current_js_object.Bind(receiver); | 5023 current_js_object.Bind(receiver); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5008 Heap::kTheHoleValueRootIndex); | 5137 Heap::kTheHoleValueRootIndex); |
5009 | 5138 |
5010 // Store the WeakCell in the feedback vector. | 5139 // Store the WeakCell in the feedback vector. |
5011 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5140 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
5012 CodeStubAssembler::SMI_PARAMETERS); | 5141 CodeStubAssembler::SMI_PARAMETERS); |
5013 return cell; | 5142 return cell; |
5014 } | 5143 } |
5015 | 5144 |
5016 } // namespace internal | 5145 } // namespace internal |
5017 } // namespace v8 | 5146 } // namespace v8 |
OLD | NEW |