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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1328 Heap::RootListIndex root_index) { | 1328 Heap::RootListIndex root_index) { |
1329 if (Heap::RootIsImmortalImmovable(root_index)) { | 1329 if (Heap::RootIsImmortalImmovable(root_index)) { |
1330 return StoreObjectFieldNoWriteBarrier(object, offset, LoadRoot(root_index)); | 1330 return StoreObjectFieldNoWriteBarrier(object, offset, LoadRoot(root_index)); |
1331 } else { | 1331 } else { |
1332 return StoreObjectField(object, offset, LoadRoot(root_index)); | 1332 return StoreObjectField(object, offset, LoadRoot(root_index)); |
1333 } | 1333 } |
1334 } | 1334 } |
1335 | 1335 |
1336 Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node, | 1336 Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node, |
1337 Node* value, | 1337 Node* value, |
1338 int additional_offset, | |
rmcilroy
2016/11/21 17:25:18
Would it be worth reordering these so that you don
Igor Sheludko
2016/11/22 12:05:07
+1. And if you put additional parameter after Writ
Jakob Kummerow
2016/11/22 13:47:57
Done.
| |
1338 WriteBarrierMode barrier_mode, | 1339 WriteBarrierMode barrier_mode, |
1339 ParameterMode parameter_mode) { | 1340 ParameterMode parameter_mode) { |
1340 DCHECK(barrier_mode == SKIP_WRITE_BARRIER || | 1341 DCHECK(barrier_mode == SKIP_WRITE_BARRIER || |
1341 barrier_mode == UPDATE_WRITE_BARRIER); | 1342 barrier_mode == UPDATE_WRITE_BARRIER); |
1342 Node* offset = | 1343 int header_size = |
1343 ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, parameter_mode, | 1344 FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; |
1344 FixedArray::kHeaderSize - kHeapObjectTag); | 1345 Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, |
1346 parameter_mode, header_size); | |
1345 MachineRepresentation rep = MachineRepresentation::kTagged; | 1347 MachineRepresentation rep = MachineRepresentation::kTagged; |
1346 if (barrier_mode == SKIP_WRITE_BARRIER) { | 1348 if (barrier_mode == SKIP_WRITE_BARRIER) { |
1347 return StoreNoWriteBarrier(rep, object, offset, value); | 1349 return StoreNoWriteBarrier(rep, object, offset, value); |
1348 } else { | 1350 } else { |
1349 return Store(rep, object, offset, value); | 1351 return Store(rep, object, offset, value); |
1350 } | 1352 } |
1351 } | 1353 } |
1352 | 1354 |
1353 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( | 1355 Node* CodeStubAssembler::StoreFixedDoubleArrayElement( |
1354 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { | 1356 Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) { |
(...skipping 2674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4029 Node* capacity = IntPtrRoundUpToPowerOfTwo32( | 4031 Node* capacity = IntPtrRoundUpToPowerOfTwo32( |
4030 WordShl(at_least_space_for, IntPtrConstant(1))); | 4032 WordShl(at_least_space_for, IntPtrConstant(1))); |
4031 return IntPtrMax(capacity, IntPtrConstant(HashTableBase::kMinCapacity)); | 4033 return IntPtrMax(capacity, IntPtrConstant(HashTableBase::kMinCapacity)); |
4032 } | 4034 } |
4033 | 4035 |
4034 Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) { | 4036 Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) { |
4035 return Select(IntPtrGreaterThanOrEqual(left, right), left, right, | 4037 return Select(IntPtrGreaterThanOrEqual(left, right), left, right, |
4036 MachineType::PointerRepresentation()); | 4038 MachineType::PointerRepresentation()); |
4037 } | 4039 } |
4038 | 4040 |
4041 template <class Dictionary> | |
4042 Node* CodeStubAssembler::GetNumberOfElements(Node* dictionary) { | |
4043 return LoadFixedArrayElement( | |
4044 dictionary, IntPtrConstant(Dictionary::kNumberOfElementsIndex), 0, | |
4045 INTPTR_PARAMETERS); | |
4046 } | |
4047 | |
4048 template <class Dictionary> | |
4049 void CodeStubAssembler::SetNumberOfElements(Node* dictionary, | |
4050 Node* num_elements_smi) { | |
4051 StoreFixedArrayElement( | |
4052 dictionary, IntPtrConstant(Dictionary::kNumberOfElementsIndex), | |
4053 num_elements_smi, 0, SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); | |
4054 } | |
4055 | |
4056 template <class Dictionary> | |
4057 Node* CodeStubAssembler::GetCapacity(Node* dictionary) { | |
4058 return LoadFixedArrayElement(dictionary, | |
4059 IntPtrConstant(Dictionary::kCapacityIndex), 0, | |
4060 INTPTR_PARAMETERS); | |
4061 } | |
4062 | |
4063 template <class Dictionary> | |
4064 Node* CodeStubAssembler::GetNextEnumerationIndex(Node* dictionary) { | |
4065 return LoadFixedArrayElement( | |
4066 dictionary, IntPtrConstant(Dictionary::kNextEnumerationIndexIndex), 0, | |
4067 INTPTR_PARAMETERS); | |
4068 } | |
4069 | |
4070 template <class Dictionary> | |
4071 void CodeStubAssembler::SetNextEnumerationIndex(Node* dictionary, | |
4072 Node* next_enum_index_smi) { | |
4073 StoreFixedArrayElement( | |
4074 dictionary, IntPtrConstant(Dictionary::kNextEnumerationIndexIndex), | |
4075 next_enum_index_smi, 0, SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); | |
4076 } | |
4077 | |
4039 template <typename Dictionary> | 4078 template <typename Dictionary> |
4040 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, | 4079 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
4041 Node* unique_name, Label* if_found, | 4080 Node* unique_name, Label* if_found, |
4042 Variable* var_name_index, | 4081 Variable* var_name_index, |
4043 Label* if_not_found, | 4082 Label* if_not_found, |
4044 int inlined_probes) { | 4083 int inlined_probes, |
4084 LookupMode mode) { | |
4045 CSA_ASSERT(this, IsDictionary(dictionary)); | 4085 CSA_ASSERT(this, IsDictionary(dictionary)); |
4046 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); | 4086 DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); |
4087 DCHECK_IMPLIES(mode == kFindInsertionIndex, | |
4088 inlined_probes == 0 && if_found == nullptr); | |
4047 Comment("NameDictionaryLookup"); | 4089 Comment("NameDictionaryLookup"); |
4048 | 4090 |
4049 Node* capacity = SmiUntag(LoadFixedArrayElement( | 4091 Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); |
4050 dictionary, IntPtrConstant(Dictionary::kCapacityIndex), 0, | |
4051 INTPTR_PARAMETERS)); | |
4052 Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); | 4092 Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); |
4053 Node* hash = ChangeUint32ToWord(LoadNameHash(unique_name)); | 4093 Node* hash = ChangeUint32ToWord(LoadNameHash(unique_name)); |
4054 | 4094 |
4055 // See Dictionary::FirstProbe(). | 4095 // See Dictionary::FirstProbe(). |
4056 Node* count = IntPtrConstant(0); | 4096 Node* count = IntPtrConstant(0); |
4057 Node* entry = WordAnd(hash, mask); | 4097 Node* entry = WordAnd(hash, mask); |
4058 | 4098 |
4059 for (int i = 0; i < inlined_probes; i++) { | 4099 for (int i = 0; i < inlined_probes; i++) { |
4060 Node* index = EntryToIndex<Dictionary>(entry); | 4100 Node* index = EntryToIndex<Dictionary>(entry); |
4061 var_name_index->Bind(index); | 4101 var_name_index->Bind(index); |
4062 | 4102 |
4063 Node* current = | 4103 Node* current = |
4064 LoadFixedArrayElement(dictionary, index, 0, INTPTR_PARAMETERS); | 4104 LoadFixedArrayElement(dictionary, index, 0, INTPTR_PARAMETERS); |
4065 GotoIf(WordEqual(current, unique_name), if_found); | 4105 GotoIf(WordEqual(current, unique_name), if_found); |
4066 | 4106 |
4067 // See Dictionary::NextProbe(). | 4107 // See Dictionary::NextProbe(). |
4068 count = IntPtrConstant(i + 1); | 4108 count = IntPtrConstant(i + 1); |
4069 entry = WordAnd(IntPtrAdd(entry, count), mask); | 4109 entry = WordAnd(IntPtrAdd(entry, count), mask); |
4070 } | 4110 } |
4111 if (mode == kFindInsertionIndex) { | |
4112 // Appease the variable merging algorithm for "Goto(&loop)" below. | |
4113 var_name_index->Bind(IntPtrConstant(0)); | |
4114 } | |
4071 | 4115 |
4072 Node* undefined = UndefinedConstant(); | 4116 Node* undefined = UndefinedConstant(); |
4117 Node* the_hole = mode == kFindExisting ? nullptr : TheHoleConstant(); | |
4073 | 4118 |
4074 Variable var_count(this, MachineType::PointerRepresentation()); | 4119 Variable var_count(this, MachineType::PointerRepresentation()); |
4075 Variable var_entry(this, MachineType::PointerRepresentation()); | 4120 Variable var_entry(this, MachineType::PointerRepresentation()); |
4076 Variable* loop_vars[] = {&var_count, &var_entry, var_name_index}; | 4121 Variable* loop_vars[] = {&var_count, &var_entry, var_name_index}; |
4077 Label loop(this, 3, loop_vars); | 4122 Label loop(this, 3, loop_vars); |
4078 var_count.Bind(count); | 4123 var_count.Bind(count); |
4079 var_entry.Bind(entry); | 4124 var_entry.Bind(entry); |
4080 Goto(&loop); | 4125 Goto(&loop); |
4081 Bind(&loop); | 4126 Bind(&loop); |
4082 { | 4127 { |
4083 Node* count = var_count.value(); | 4128 Node* count = var_count.value(); |
4084 Node* entry = var_entry.value(); | 4129 Node* entry = var_entry.value(); |
4085 | 4130 |
4086 Node* index = EntryToIndex<Dictionary>(entry); | 4131 Node* index = EntryToIndex<Dictionary>(entry); |
4087 var_name_index->Bind(index); | 4132 var_name_index->Bind(index); |
4088 | 4133 |
4089 Node* current = | 4134 Node* current = |
4090 LoadFixedArrayElement(dictionary, index, 0, INTPTR_PARAMETERS); | 4135 LoadFixedArrayElement(dictionary, index, 0, INTPTR_PARAMETERS); |
4091 GotoIf(WordEqual(current, undefined), if_not_found); | 4136 GotoIf(WordEqual(current, undefined), if_not_found); |
4092 GotoIf(WordEqual(current, unique_name), if_found); | 4137 if (mode == kFindExisting) { |
4138 GotoIf(WordEqual(current, unique_name), if_found); | |
4139 } else { | |
4140 DCHECK(mode == kFindInsertionIndex); | |
Igor Sheludko
2016/11/22 12:05:08
DCHECK_EQ
Jakob Kummerow
2016/11/22 13:47:57
Done. (FWIW, I disagree with the preference -- I t
| |
4141 GotoIf(WordEqual(current, the_hole), if_not_found); | |
4142 } | |
4093 | 4143 |
4094 // See Dictionary::NextProbe(). | 4144 // See Dictionary::NextProbe(). |
4095 count = IntPtrAdd(count, IntPtrConstant(1)); | 4145 count = IntPtrAdd(count, IntPtrConstant(1)); |
4096 entry = WordAnd(IntPtrAdd(entry, count), mask); | 4146 entry = WordAnd(IntPtrAdd(entry, count), mask); |
4097 | 4147 |
4098 var_count.Bind(count); | 4148 var_count.Bind(count); |
4099 var_entry.Bind(entry); | 4149 var_entry.Bind(entry); |
4100 Goto(&loop); | 4150 Goto(&loop); |
4101 } | 4151 } |
4102 } | 4152 } |
4103 | 4153 |
4104 // Instantiate template methods to workaround GCC compilation issue. | 4154 // Instantiate template methods to workaround GCC compilation issue. |
4105 template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( | 4155 template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( |
4106 Node*, Node*, Label*, Variable*, Label*, int); | 4156 Node*, Node*, Label*, Variable*, Label*, int, LookupMode); |
4107 template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( | 4157 template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( |
4108 Node*, Node*, Label*, Variable*, Label*, int); | 4158 Node*, Node*, Label*, Variable*, Label*, int, LookupMode); |
4109 | 4159 |
4110 Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) { | 4160 Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) { |
4111 // See v8::internal::ComputeIntegerHash() | 4161 // See v8::internal::ComputeIntegerHash() |
4112 Node* hash = key; | 4162 Node* hash = key; |
4113 hash = Word32Xor(hash, seed); | 4163 hash = Word32Xor(hash, seed); |
4114 hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)), | 4164 hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)), |
4115 Word32Shl(hash, Int32Constant(15))); | 4165 Word32Shl(hash, Int32Constant(15))); |
4116 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); | 4166 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12))); |
4117 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); | 4167 hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2))); |
4118 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); | 4168 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4))); |
4119 hash = Int32Mul(hash, Int32Constant(2057)); | 4169 hash = Int32Mul(hash, Int32Constant(2057)); |
4120 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); | 4170 hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16))); |
4121 return Word32And(hash, Int32Constant(0x3fffffff)); | 4171 return Word32And(hash, Int32Constant(0x3fffffff)); |
4122 } | 4172 } |
4123 | 4173 |
4124 template <typename Dictionary> | 4174 template <typename Dictionary> |
4125 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, | 4175 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
4126 Node* intptr_index, | 4176 Node* intptr_index, |
4127 Label* if_found, | 4177 Label* if_found, |
4128 Variable* var_entry, | 4178 Variable* var_entry, |
4129 Label* if_not_found) { | 4179 Label* if_not_found) { |
4130 CSA_ASSERT(this, IsDictionary(dictionary)); | 4180 CSA_ASSERT(this, IsDictionary(dictionary)); |
4131 DCHECK_EQ(MachineType::PointerRepresentation(), var_entry->rep()); | 4181 DCHECK_EQ(MachineType::PointerRepresentation(), var_entry->rep()); |
4132 Comment("NumberDictionaryLookup"); | 4182 Comment("NumberDictionaryLookup"); |
4133 | 4183 |
4134 Node* capacity = SmiUntag(LoadFixedArrayElement( | 4184 Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); |
4135 dictionary, IntPtrConstant(Dictionary::kCapacityIndex), 0, | |
4136 INTPTR_PARAMETERS)); | |
4137 Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); | 4185 Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); |
4138 | 4186 |
4139 Node* int32_seed; | 4187 Node* int32_seed; |
4140 if (Dictionary::ShapeT::UsesSeed) { | 4188 if (Dictionary::ShapeT::UsesSeed) { |
4141 int32_seed = HashSeed(); | 4189 int32_seed = HashSeed(); |
4142 } else { | 4190 } else { |
4143 int32_seed = Int32Constant(kZeroHashSeed); | 4191 int32_seed = Int32Constant(kZeroHashSeed); |
4144 } | 4192 } |
4145 Node* hash = ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed)); | 4193 Node* hash = ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed)); |
4146 Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index); | 4194 Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4190 // See Dictionary::NextProbe(). | 4238 // See Dictionary::NextProbe(). |
4191 count = IntPtrAdd(count, IntPtrConstant(1)); | 4239 count = IntPtrAdd(count, IntPtrConstant(1)); |
4192 entry = WordAnd(IntPtrAdd(entry, count), mask); | 4240 entry = WordAnd(IntPtrAdd(entry, count), mask); |
4193 | 4241 |
4194 var_count.Bind(count); | 4242 var_count.Bind(count); |
4195 var_entry->Bind(entry); | 4243 var_entry->Bind(entry); |
4196 Goto(&loop); | 4244 Goto(&loop); |
4197 } | 4245 } |
4198 } | 4246 } |
4199 | 4247 |
4248 template <class Dictionary> | |
4249 void CodeStubAssembler::FindInsertionEntry(Node* dictionary, Node* key, | |
4250 Variable* var_key_index) { | |
4251 UNREACHABLE(); | |
4252 } | |
4253 | |
4254 template <> | |
4255 void CodeStubAssembler::FindInsertionEntry<NameDictionary>( | |
4256 Node* dictionary, Node* key, Variable* var_key_index) { | |
4257 Label done(this); | |
4258 NameDictionaryLookup<NameDictionary>(dictionary, key, nullptr, var_key_index, | |
4259 &done, 0, kFindInsertionIndex); | |
4260 Bind(&done); | |
4261 } | |
4262 | |
4263 template <class Dictionary> | |
4264 void CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value, | |
Igor Sheludko
2016/11/22 12:05:07
This implementation is not fully applicable for Gl
Jakob Kummerow
2016/11/22 13:47:57
Done. (Pulled out the second half as "InsertEntry<
| |
4265 Label* bailout) { | |
4266 Node* capacity = GetCapacity<Dictionary>(dictionary); | |
4267 Node* nof = GetNumberOfElements<Dictionary>(dictionary); | |
4268 Node* new_nof = SmiAdd(nof, SmiConstant(1)); | |
4269 // Require 33% to still be free after adding additional_elements. | |
4270 // This is a simplification of the C++ implementation's behavior, which | |
4271 // also rehashes the dictionary when there are too many deleted elements. | |
4272 // Computing "x + (x >> 1)" on a Smi x does not return a valid Smi! | |
4273 // But that's OK here because it's only used for a comparison. | |
4274 Node* required_capacity_pseudo_smi = SmiAdd(new_nof, WordShr(new_nof, 1)); | |
4275 GotoIf(UintPtrLessThan(capacity, required_capacity_pseudo_smi), bailout); | |
4276 Node* enum_index = nullptr; | |
4277 if (Dictionary::kIsEnumerable) { | |
4278 enum_index = GetNextEnumerationIndex<Dictionary>(dictionary); | |
4279 Node* new_enum_index = SmiAdd(enum_index, SmiConstant(1)); | |
4280 Node* max_enum_index = SmiConstant( | |
4281 Smi::FromInt(PropertyDetails::DictionaryStorageField::kMax)); | |
Igor Sheludko
2016/11/22 12:05:07
Can you drop Smi::FromInt?
Jakob Kummerow
2016/11/22 13:47:57
Done.
| |
4282 GotoIf(UintPtrGreaterThan(new_enum_index, max_enum_index), bailout); | |
4283 | |
4284 // No more bailouts after this point. | |
4285 // Operations from here on can have side effects. | |
4286 | |
4287 SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index); | |
4288 } else { | |
4289 USE(enum_index); | |
4290 } | |
4291 SetNumberOfElements<Dictionary>(dictionary, new_nof); | |
4292 | |
4293 Variable var_key_index(this, MachineType::PointerRepresentation()); | |
4294 FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index); | |
4295 Node* index = var_key_index.value(); | |
4296 StoreFixedArrayElement(dictionary, index, key, 0, UPDATE_WRITE_BARRIER, | |
4297 INTPTR_PARAMETERS); | |
4298 const int kNameToValueOffset = | |
4299 (Dictionary::kEntryValueIndex - Dictionary::kEntryKeyIndex) * | |
4300 kPointerSize; | |
4301 StoreFixedArrayElement(dictionary, index, value, kNameToValueOffset, | |
4302 UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS); | |
4303 if (Dictionary::kIsEnumerable) { | |
Igor Sheludko
2016/11/22 12:05:07
Shoudn't we also set details if the dictionary is
Jakob Kummerow
2016/11/22 13:47:57
Oops, good point. Done.
| |
4304 const int kInitialIndex = 0; | |
4305 PropertyDetails d(NONE, DATA, kInitialIndex, PropertyCellType::kNoCell); | |
4306 Node* details = SmiConstant(d.AsSmi()); | |
4307 enum_index = | |
4308 WordShl(enum_index, PropertyDetails::DictionaryStorageField::kShift); | |
4309 STATIC_ASSERT(kInitialIndex == 0); | |
4310 details = WordOr(details, enum_index); | |
4311 const int kNameToDetailsOffset = | |
4312 (Dictionary::kEntryDetailsIndex - Dictionary::kEntryKeyIndex) * | |
4313 kPointerSize; | |
4314 StoreFixedArrayElement(dictionary, index, details, kNameToDetailsOffset, | |
4315 SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); | |
4316 } | |
4317 } | |
4318 | |
4319 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, | |
4320 Label*); | |
4321 | |
4200 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, | 4322 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, |
4201 Node* descriptors, Node* nof, | 4323 Node* descriptors, Node* nof, |
4202 Label* if_found, | 4324 Label* if_found, |
4203 Variable* var_name_index, | 4325 Variable* var_name_index, |
4204 Label* if_not_found) { | 4326 Label* if_not_found) { |
4205 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); | 4327 Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0)); |
4206 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); | 4328 Node* factor = IntPtrConstant(DescriptorArray::kDescriptorSize); |
4207 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); | 4329 Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor)); |
4208 | 4330 |
4209 BuildFastLoop( | 4331 BuildFastLoop( |
(...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4975 compiler::Node* type_feedback_vector, | 5097 compiler::Node* type_feedback_vector, |
4976 compiler::Node* slot_id) { | 5098 compiler::Node* slot_id) { |
4977 // This method is used for binary op and compare feedback. These | 5099 // This method is used for binary op and compare feedback. These |
4978 // vector nodes are initialized with a smi 0, so we can simply OR | 5100 // vector nodes are initialized with a smi 0, so we can simply OR |
4979 // our new feedback in place. | 5101 // our new feedback in place. |
4980 // TODO(interpreter): Consider passing the feedback as Smi already to avoid | 5102 // TODO(interpreter): Consider passing the feedback as Smi already to avoid |
4981 // the tagging completely. | 5103 // the tagging completely. |
4982 Node* previous_feedback = | 5104 Node* previous_feedback = |
4983 LoadFixedArrayElement(type_feedback_vector, slot_id); | 5105 LoadFixedArrayElement(type_feedback_vector, slot_id); |
4984 Node* combined_feedback = SmiOr(previous_feedback, SmiFromWord32(feedback)); | 5106 Node* combined_feedback = SmiOr(previous_feedback, SmiFromWord32(feedback)); |
4985 StoreFixedArrayElement(type_feedback_vector, slot_id, combined_feedback, | 5107 StoreFixedArrayElement(type_feedback_vector, slot_id, combined_feedback, 0, |
4986 SKIP_WRITE_BARRIER); | 5108 SKIP_WRITE_BARRIER); |
4987 } | 5109 } |
4988 | 5110 |
4989 compiler::Node* CodeStubAssembler::LoadReceiverMap(compiler::Node* receiver) { | 5111 compiler::Node* CodeStubAssembler::LoadReceiverMap(compiler::Node* receiver) { |
4990 Variable var_receiver_map(this, MachineRepresentation::kTagged); | 5112 Variable var_receiver_map(this, MachineRepresentation::kTagged); |
4991 Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), | 5113 Label load_smi_map(this, Label::kDeferred), load_receiver_map(this), |
4992 if_result(this); | 5114 if_result(this); |
4993 | 5115 |
4994 Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); | 5116 Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map); |
4995 Bind(&load_smi_map); | 5117 Bind(&load_smi_map); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5186 // methods for accessing Context. | 5308 // methods for accessing Context. |
5187 STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize); | 5309 STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize); |
5188 DCHECK_EQ(Context::SlotOffset(0) + kHeapObjectTag, | 5310 DCHECK_EQ(Context::SlotOffset(0) + kHeapObjectTag, |
5189 FixedArray::OffsetOfElementAt(0)); | 5311 FixedArray::OffsetOfElementAt(0)); |
5190 if (is_load) { | 5312 if (is_load) { |
5191 Node* result = LoadFixedArrayElement(the_context, mapped_index, 0, | 5313 Node* result = LoadFixedArrayElement(the_context, mapped_index, 0, |
5192 INTPTR_PARAMETERS); | 5314 INTPTR_PARAMETERS); |
5193 CSA_ASSERT(this, WordNotEqual(result, TheHoleConstant())); | 5315 CSA_ASSERT(this, WordNotEqual(result, TheHoleConstant())); |
5194 var_result.Bind(result); | 5316 var_result.Bind(result); |
5195 } else { | 5317 } else { |
5196 StoreFixedArrayElement(the_context, mapped_index, value, | 5318 StoreFixedArrayElement(the_context, mapped_index, value, 0, |
5197 UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS); | 5319 UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS); |
5198 } | 5320 } |
5199 Goto(&end); | 5321 Goto(&end); |
5200 } | 5322 } |
5201 | 5323 |
5202 Bind(&if_unmapped); | 5324 Bind(&if_unmapped); |
5203 { | 5325 { |
5204 Node* backing_store = LoadFixedArrayElement(elements, IntPtrConstant(1), 0, | 5326 Node* backing_store = LoadFixedArrayElement(elements, IntPtrConstant(1), 0, |
5205 INTPTR_PARAMETERS); | 5327 INTPTR_PARAMETERS); |
5206 GotoIf(WordNotEqual(LoadMap(backing_store), FixedArrayMapConstant()), | 5328 GotoIf(WordNotEqual(LoadMap(backing_store), FixedArrayMapConstant()), |
5207 bailout); | 5329 bailout); |
5208 | 5330 |
5209 Node* backing_store_length = | 5331 Node* backing_store_length = |
5210 LoadAndUntagFixedArrayBaseLength(backing_store); | 5332 LoadAndUntagFixedArrayBaseLength(backing_store); |
5211 GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout); | 5333 GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout); |
5212 | 5334 |
5213 // The key falls into unmapped range. | 5335 // The key falls into unmapped range. |
5214 if (is_load) { | 5336 if (is_load) { |
5215 Node* result = | 5337 Node* result = |
5216 LoadFixedArrayElement(backing_store, key, 0, INTPTR_PARAMETERS); | 5338 LoadFixedArrayElement(backing_store, key, 0, INTPTR_PARAMETERS); |
5217 GotoIf(WordEqual(result, TheHoleConstant()), bailout); | 5339 GotoIf(WordEqual(result, TheHoleConstant()), bailout); |
5218 var_result.Bind(result); | 5340 var_result.Bind(result); |
5219 } else { | 5341 } else { |
5220 StoreFixedArrayElement(backing_store, key, value, UPDATE_WRITE_BARRIER, | 5342 StoreFixedArrayElement(backing_store, key, value, 0, UPDATE_WRITE_BARRIER, |
5221 INTPTR_PARAMETERS); | 5343 INTPTR_PARAMETERS); |
5222 } | 5344 } |
5223 Goto(&end); | 5345 Goto(&end); |
5224 } | 5346 } |
5225 | 5347 |
5226 Bind(&end); | 5348 Bind(&end); |
5227 return var_result.value(); | 5349 return var_result.value(); |
5228 } | 5350 } |
5229 | 5351 |
5230 Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) { | 5352 Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5293 return; | 5415 return; |
5294 } | 5416 } |
5295 | 5417 |
5296 WriteBarrierMode barrier_mode = | 5418 WriteBarrierMode barrier_mode = |
5297 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 5419 IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
5298 if (IsFastDoubleElementsKind(kind)) { | 5420 if (IsFastDoubleElementsKind(kind)) { |
5299 // Make sure we do not store signalling NaNs into double arrays. | 5421 // Make sure we do not store signalling NaNs into double arrays. |
5300 value = Float64SilenceNaN(value); | 5422 value = Float64SilenceNaN(value); |
5301 StoreFixedDoubleArrayElement(elements, index, value, mode); | 5423 StoreFixedDoubleArrayElement(elements, index, value, mode); |
5302 } else { | 5424 } else { |
5303 StoreFixedArrayElement(elements, index, value, barrier_mode, mode); | 5425 StoreFixedArrayElement(elements, index, value, 0, barrier_mode, mode); |
5304 } | 5426 } |
5305 } | 5427 } |
5306 | 5428 |
5307 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, | 5429 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, |
5308 bool is_jsarray, | 5430 bool is_jsarray, |
5309 ElementsKind elements_kind, | 5431 ElementsKind elements_kind, |
5310 KeyedAccessStoreMode store_mode, | 5432 KeyedAccessStoreMode store_mode, |
5311 Label* bailout) { | 5433 Label* bailout) { |
5312 Node* elements = LoadElements(object); | 5434 Node* elements = LoadElements(object); |
5313 if (IsFastSmiOrObjectElementsKind(elements_kind) && | 5435 if (IsFastSmiOrObjectElementsKind(elements_kind) && |
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5685 Node* next_site = LoadBufferObject(site_list, 0); | 5807 Node* next_site = LoadBufferObject(site_list, 0); |
5686 | 5808 |
5687 // TODO(mvstanton): This is a store to a weak pointer, which we may want to | 5809 // TODO(mvstanton): This is a store to a weak pointer, which we may want to |
5688 // mark as such in order to skip the write barrier, once we have a unified | 5810 // mark as such in order to skip the write barrier, once we have a unified |
5689 // system for weakness. For now we decided to keep it like this because having | 5811 // system for weakness. For now we decided to keep it like this because having |
5690 // an initial write barrier backed store makes this pointer strong until the | 5812 // an initial write barrier backed store makes this pointer strong until the |
5691 // next GC, and allocation sites are designed to survive several GCs anyway. | 5813 // next GC, and allocation sites are designed to survive several GCs anyway. |
5692 StoreObjectField(site, AllocationSite::kWeakNextOffset, next_site); | 5814 StoreObjectField(site, AllocationSite::kWeakNextOffset, next_site); |
5693 StoreNoWriteBarrier(MachineRepresentation::kTagged, site_list, site); | 5815 StoreNoWriteBarrier(MachineRepresentation::kTagged, site_list, site); |
5694 | 5816 |
5695 StoreFixedArrayElement(feedback_vector, slot, site, UPDATE_WRITE_BARRIER, | 5817 StoreFixedArrayElement(feedback_vector, slot, site, 0, UPDATE_WRITE_BARRIER, |
5696 CodeStubAssembler::SMI_PARAMETERS); | 5818 CodeStubAssembler::SMI_PARAMETERS); |
5697 return site; | 5819 return site; |
5698 } | 5820 } |
5699 | 5821 |
5700 Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector, | 5822 Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector, |
5701 Node* slot, | 5823 Node* slot, |
5702 Node* value) { | 5824 Node* value) { |
5703 Node* size = IntPtrConstant(WeakCell::kSize); | 5825 Node* size = IntPtrConstant(WeakCell::kSize); |
5704 Node* cell = Allocate(size, CodeStubAssembler::kPretenured); | 5826 Node* cell = Allocate(size, CodeStubAssembler::kPretenured); |
5705 | 5827 |
5706 // Initialize the WeakCell. | 5828 // Initialize the WeakCell. |
5707 StoreObjectFieldRoot(cell, WeakCell::kMapOffset, Heap::kWeakCellMapRootIndex); | 5829 StoreObjectFieldRoot(cell, WeakCell::kMapOffset, Heap::kWeakCellMapRootIndex); |
5708 StoreObjectField(cell, WeakCell::kValueOffset, value); | 5830 StoreObjectField(cell, WeakCell::kValueOffset, value); |
5709 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, | 5831 StoreObjectFieldRoot(cell, WeakCell::kNextOffset, |
5710 Heap::kTheHoleValueRootIndex); | 5832 Heap::kTheHoleValueRootIndex); |
5711 | 5833 |
5712 // Store the WeakCell in the feedback vector. | 5834 // Store the WeakCell in the feedback vector. |
5713 StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, | 5835 StoreFixedArrayElement(feedback_vector, slot, cell, 0, UPDATE_WRITE_BARRIER, |
5714 CodeStubAssembler::SMI_PARAMETERS); | 5836 CodeStubAssembler::SMI_PARAMETERS); |
5715 return cell; | 5837 return cell; |
5716 } | 5838 } |
5717 | 5839 |
5718 void CodeStubAssembler::BuildFastLoop( | 5840 void CodeStubAssembler::BuildFastLoop( |
5719 const CodeStubAssembler::VariableList& vars, | 5841 const CodeStubAssembler::VariableList& vars, |
5720 MachineRepresentation index_rep, Node* start_index, Node* end_index, | 5842 MachineRepresentation index_rep, Node* start_index, Node* end_index, |
5721 std::function<void(CodeStubAssembler* assembler, Node* index)> body, | 5843 std::function<void(CodeStubAssembler* assembler, Node* index)> body, |
5722 int increment, IndexAdvanceMode mode) { | 5844 int increment, IndexAdvanceMode mode) { |
5723 Variable var(this, index_rep); | 5845 Variable var(this, index_rep); |
(...skipping 1987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7711 | 7833 |
7712 compiler::Node* CodeStubAssembler::IsDebugActive() { | 7834 compiler::Node* CodeStubAssembler::IsDebugActive() { |
7713 Node* is_debug_active = Load( | 7835 Node* is_debug_active = Load( |
7714 MachineType::Uint8(), | 7836 MachineType::Uint8(), |
7715 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); | 7837 ExternalConstant(ExternalReference::debug_is_active_address(isolate()))); |
7716 return WordNotEqual(is_debug_active, Int32Constant(0)); | 7838 return WordNotEqual(is_debug_active, Int32Constant(0)); |
7717 } | 7839 } |
7718 | 7840 |
7719 } // namespace internal | 7841 } // namespace internal |
7720 } // namespace v8 | 7842 } // namespace v8 |
OLD | NEW |