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

Side by Side Diff: src/ic/keyed-store-generic.cc

Issue 2444353002: [stubs] Port KeyedStoreIC_Megamorphic stub to Turbofan (Closed)
Patch Set: rebased Created 4 years, 1 month 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/ic/keyed-store-generic.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "src/ic/keyed-store-generic.h"
6
7 #include "src/compiler/code-assembler.h"
8 #include "src/contexts.h"
9 #include "src/isolate.h"
10
11 namespace v8 {
12 namespace internal {
13
14 using compiler::Node;
15
16 class KeyedStoreGenericAssembler : public CodeStubAssembler {
17 public:
18 void KeyedStoreGeneric(const StoreICParameters* p,
19 LanguageMode language_mode);
20
21 private:
22 enum UpdateLength {
23 kDontChangeLength,
24 kIncrementLengthByOne,
25 kBumpLengthWithGap
26 };
27
28 void EmitGenericElementStore(Node* receiver, Node* receiver_map,
29 Node* instance_type, Node* intptr_index,
30 Node* value, Node* context, Label* slow);
31
32 void EmitGenericPropertyStore(Node* receiver, Node* receiver_map,
33 const StoreICParameters* p, Label* slow);
34
35 void BranchIfPrototypesHaveNonFastElements(Node* receiver_map,
36 Label* non_fast_elements,
37 Label* only_fast_elements);
38
39 void TryRewriteElements(Node* receiver, Node* receiver_map, Node* elements,
40 Node* native_context, ElementsKind from_kind,
41 ElementsKind to_kind, Label* bailout);
42
43 void StoreElementWithCapacity(Node* receiver, Node* receiver_map,
44 Node* elements, Node* elements_kind,
45 Node* intptr_index, Node* value, Node* context,
46 Label* slow, UpdateLength update_length);
47
48 void MaybeUpdateLengthAndReturn(Node* receiver, Node* index, Node* value,
49 UpdateLength update_length);
50
51 void TryChangeToHoleyMapHelper(Node* receiver, Node* receiver_map,
52 Node* native_context, ElementsKind packed_kind,
53 ElementsKind holey_kind, Label* done,
54 Label* map_mismatch, Label* bailout);
55 void TryChangeToHoleyMap(Node* receiver, Node* receiver_map,
56 Node* current_elements_kind, Node* context,
57 ElementsKind packed_kind, Label* bailout);
58 void TryChangeToHoleyMapMulti(Node* receiver, Node* receiver_map,
59 Node* current_elements_kind, Node* context,
60 ElementsKind packed_kind,
61 ElementsKind packed_kind_2, Label* bailout);
62
63 // Do not add fields, so that this is safe to reinterpret_cast to CSA.
64 };
65
66 void KeyedStoreGenericGenerator::Generate(
67 CodeStubAssembler* assembler, const CodeStubAssembler::StoreICParameters* p,
68 LanguageMode language_mode) {
69 STATIC_ASSERT(sizeof(CodeStubAssembler) ==
70 sizeof(KeyedStoreGenericAssembler));
71 auto assm = reinterpret_cast<KeyedStoreGenericAssembler*>(assembler);
hans 2016/11/14 22:16:01 This looks like a hack, and the reason for the UBS
72 assm->KeyedStoreGeneric(p, language_mode);
73 }
74
75 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
76 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
77 Variable var_map(this, MachineRepresentation::kTagged);
78 var_map.Bind(receiver_map);
79 Label loop_body(this, &var_map);
80 Goto(&loop_body);
81
82 Bind(&loop_body);
83 {
84 Node* map = var_map.value();
85 Node* prototype = LoadMapPrototype(map);
86 GotoIf(WordEqual(prototype, NullConstant()), only_fast_elements);
87 Node* prototype_map = LoadMap(prototype);
88 var_map.Bind(prototype_map);
89 Node* instance_type = LoadMapInstanceType(prototype_map);
90 STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE);
91 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE);
92 GotoIf(Int32LessThanOrEqual(instance_type,
93 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
94 non_fast_elements);
95 Node* elements_kind = LoadMapElementsKind(prototype_map);
96 STATIC_ASSERT(FIRST_ELEMENTS_KIND == FIRST_FAST_ELEMENTS_KIND);
97 GotoIf(Int32LessThanOrEqual(elements_kind,
98 Int32Constant(LAST_FAST_ELEMENTS_KIND)),
99 &loop_body);
100 GotoIf(Word32Equal(elements_kind, Int32Constant(NO_ELEMENTS)), &loop_body);
101 Goto(non_fast_elements);
102 }
103 }
104
105 void KeyedStoreGenericAssembler::TryRewriteElements(
106 Node* receiver, Node* receiver_map, Node* elements, Node* native_context,
107 ElementsKind from_kind, ElementsKind to_kind, Label* bailout) {
108 DCHECK(IsFastPackedElementsKind(from_kind));
109 ElementsKind holey_from_kind = GetHoleyElementsKind(from_kind);
110 ElementsKind holey_to_kind = GetHoleyElementsKind(to_kind);
111 if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
112 TrapAllocationMemento(receiver, bailout);
113 }
114 Label perform_transition(this), check_holey_map(this);
115 Variable var_target_map(this, MachineType::PointerRepresentation());
116 // Check if the receiver has the default |from_kind| map.
117 {
118 Node* packed_map =
119 LoadContextElement(native_context, Context::ArrayMapIndex(from_kind));
120 GotoIf(WordNotEqual(receiver_map, packed_map), &check_holey_map);
121 var_target_map.Bind(
122 LoadContextElement(native_context, Context::ArrayMapIndex(to_kind)));
123 Goto(&perform_transition);
124 }
125
126 // Check if the receiver has the default |holey_from_kind| map.
127 Bind(&check_holey_map);
128 {
129 Node* holey_map = LoadContextElement(
130 native_context, Context::ArrayMapIndex(holey_from_kind));
131 GotoIf(WordNotEqual(receiver_map, holey_map), bailout);
132 var_target_map.Bind(LoadContextElement(
133 native_context, Context::ArrayMapIndex(holey_to_kind)));
134 Goto(&perform_transition);
135 }
136
137 // Found a supported transition target map, perform the transition!
138 Bind(&perform_transition);
139 {
140 if (IsFastDoubleElementsKind(from_kind) !=
141 IsFastDoubleElementsKind(to_kind)) {
142 Node* capacity = LoadFixedArrayBaseLength(elements);
143 GrowElementsCapacity(receiver, elements, from_kind, to_kind, capacity,
144 capacity, INTPTR_PARAMETERS, bailout);
145 }
146 StoreObjectField(receiver, JSObject::kMapOffset, var_target_map.value());
147 }
148 }
149
150 void KeyedStoreGenericAssembler::TryChangeToHoleyMapHelper(
151 Node* receiver, Node* receiver_map, Node* native_context,
152 ElementsKind packed_kind, ElementsKind holey_kind, Label* done,
153 Label* map_mismatch, Label* bailout) {
154 Node* packed_map =
155 LoadContextElement(native_context, Context::ArrayMapIndex(packed_kind));
156 GotoIf(WordNotEqual(receiver_map, packed_map), map_mismatch);
157 if (AllocationSite::GetMode(packed_kind, holey_kind) ==
158 TRACK_ALLOCATION_SITE) {
159 TrapAllocationMemento(receiver, bailout);
160 }
161 Node* holey_map =
162 LoadContextElement(native_context, Context::ArrayMapIndex(holey_kind));
163 StoreObjectField(receiver, JSObject::kMapOffset, holey_map);
164 Goto(done);
165 }
166
167 void KeyedStoreGenericAssembler::TryChangeToHoleyMap(
168 Node* receiver, Node* receiver_map, Node* current_elements_kind,
169 Node* context, ElementsKind packed_kind, Label* bailout) {
170 ElementsKind holey_kind = GetHoleyElementsKind(packed_kind);
171 Label already_holey(this);
172
173 GotoIf(Word32Equal(current_elements_kind, Int32Constant(holey_kind)),
174 &already_holey);
175 Node* native_context = LoadNativeContext(context);
176 TryChangeToHoleyMapHelper(receiver, receiver_map, native_context, packed_kind,
177 holey_kind, &already_holey, bailout, bailout);
178 Bind(&already_holey);
179 }
180
181 void KeyedStoreGenericAssembler::TryChangeToHoleyMapMulti(
182 Node* receiver, Node* receiver_map, Node* current_elements_kind,
183 Node* context, ElementsKind packed_kind, ElementsKind packed_kind_2,
184 Label* bailout) {
185 ElementsKind holey_kind = GetHoleyElementsKind(packed_kind);
186 ElementsKind holey_kind_2 = GetHoleyElementsKind(packed_kind_2);
187 Label already_holey(this), check_other_kind(this);
188
189 GotoIf(Word32Equal(current_elements_kind, Int32Constant(holey_kind)),
190 &already_holey);
191 GotoIf(Word32Equal(current_elements_kind, Int32Constant(holey_kind_2)),
192 &already_holey);
193
194 Node* native_context = LoadNativeContext(context);
195 TryChangeToHoleyMapHelper(receiver, receiver_map, native_context, packed_kind,
196 holey_kind, &already_holey, &check_other_kind,
197 bailout);
198 Bind(&check_other_kind);
199 TryChangeToHoleyMapHelper(receiver, receiver_map, native_context,
200 packed_kind_2, holey_kind_2, &already_holey,
201 bailout, bailout);
202 Bind(&already_holey);
203 }
204
205 void KeyedStoreGenericAssembler::MaybeUpdateLengthAndReturn(
206 Node* receiver, Node* index, Node* value, UpdateLength update_length) {
207 if (update_length != kDontChangeLength) {
208 Node* new_length = SmiTag(IntPtrAdd(index, IntPtrConstant(1)));
209 StoreObjectFieldNoWriteBarrier(receiver, JSArray::kLengthOffset, new_length,
210 MachineRepresentation::kTagged);
211 }
212 Return(value);
213 }
214
215 void KeyedStoreGenericAssembler::StoreElementWithCapacity(
216 Node* receiver, Node* receiver_map, Node* elements, Node* elements_kind,
217 Node* intptr_index, Node* value, Node* context, Label* slow,
218 UpdateLength update_length) {
219 if (update_length != kDontChangeLength) {
220 CSA_ASSERT(this, Word32Equal(LoadMapInstanceType(receiver_map),
221 Int32Constant(JS_ARRAY_TYPE)));
222 }
223 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
224 const int kHeaderSize = FixedArray::kHeaderSize - kHeapObjectTag;
225
226 Label check_double_elements(this), check_cow_elements(this);
227 Node* elements_map = LoadMap(elements);
228 GotoIf(WordNotEqual(elements_map, LoadRoot(Heap::kFixedArrayMapRootIndex)),
229 &check_double_elements);
230
231 // FixedArray backing store -> Smi or object elements.
232 {
233 Node* offset = ElementOffsetFromIndex(intptr_index, FAST_ELEMENTS,
234 INTPTR_PARAMETERS, kHeaderSize);
235 // Check if we're about to overwrite the hole. We can safely do that
236 // only if there can be no setters on the prototype chain.
237 // If we know that we're storing beyond the previous array length, we
238 // can skip the hole check (and always assume the hole).
239 {
240 Label hole_check_passed(this);
241 if (update_length == kDontChangeLength) {
242 Node* element = Load(MachineType::AnyTagged(), elements, offset);
243 GotoIf(WordNotEqual(element, TheHoleConstant()), &hole_check_passed);
244 }
245 BranchIfPrototypesHaveNonFastElements(receiver_map, slow,
246 &hole_check_passed);
247 Bind(&hole_check_passed);
248 }
249
250 // Check if the value we're storing matches the elements_kind. Smis
251 // can always be stored.
252 {
253 Label non_smi_value(this);
254 GotoUnless(TaggedIsSmi(value), &non_smi_value);
255 // If we're about to introduce holes, ensure holey elements.
256 if (update_length == kBumpLengthWithGap) {
257 TryChangeToHoleyMapMulti(receiver, receiver_map, elements_kind, context,
258 FAST_SMI_ELEMENTS, FAST_ELEMENTS, slow);
259 }
260 StoreNoWriteBarrier(MachineRepresentation::kTagged, elements, offset,
261 value);
262 MaybeUpdateLengthAndReturn(receiver, intptr_index, value, update_length);
263
264 Bind(&non_smi_value);
265 }
266
267 // Check if we already have object elements; just do the store if so.
268 {
269 Label must_transition(this);
270 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0);
271 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1);
272 GotoIf(Int32LessThanOrEqual(elements_kind,
273 Int32Constant(FAST_HOLEY_SMI_ELEMENTS)),
274 &must_transition);
275 if (update_length == kBumpLengthWithGap) {
276 TryChangeToHoleyMap(receiver, receiver_map, elements_kind, context,
277 FAST_ELEMENTS, slow);
278 }
279 Store(MachineRepresentation::kTagged, elements, offset, value);
280 MaybeUpdateLengthAndReturn(receiver, intptr_index, value, update_length);
281
282 Bind(&must_transition);
283 }
284
285 // Transition to the required ElementsKind.
286 {
287 Label transition_to_double(this), transition_to_object(this);
288 Node* native_context = LoadNativeContext(context);
289 Branch(WordEqual(LoadMap(value), LoadRoot(Heap::kHeapNumberMapRootIndex)),
290 &transition_to_double, &transition_to_object);
291 Bind(&transition_to_double);
292 {
293 // If we're adding holes at the end, always transition to a holey
294 // elements kind, otherwise try to remain packed.
295 ElementsKind target_kind = update_length == kBumpLengthWithGap
296 ? FAST_HOLEY_DOUBLE_ELEMENTS
297 : FAST_DOUBLE_ELEMENTS;
298 TryRewriteElements(receiver, receiver_map, elements, native_context,
299 FAST_SMI_ELEMENTS, target_kind, slow);
300 // Reload migrated elements.
301 Node* double_elements = LoadElements(receiver);
302 Node* double_offset = ElementOffsetFromIndex(
303 intptr_index, FAST_DOUBLE_ELEMENTS, INTPTR_PARAMETERS, kHeaderSize);
304 // Make sure we do not store signalling NaNs into double arrays.
305 Node* double_value = Float64SilenceNaN(LoadHeapNumberValue(value));
306 StoreNoWriteBarrier(MachineRepresentation::kFloat64, double_elements,
307 double_offset, double_value);
308 MaybeUpdateLengthAndReturn(receiver, intptr_index, value,
309 update_length);
310 }
311
312 Bind(&transition_to_object);
313 {
314 // If we're adding holes at the end, always transition to a holey
315 // elements kind, otherwise try to remain packed.
316 ElementsKind target_kind = update_length == kBumpLengthWithGap
317 ? FAST_HOLEY_ELEMENTS
318 : FAST_ELEMENTS;
319 TryRewriteElements(receiver, receiver_map, elements, native_context,
320 FAST_SMI_ELEMENTS, target_kind, slow);
321 // The elements backing store didn't change, no reload necessary.
322 CSA_ASSERT(this, WordEqual(elements, LoadElements(receiver)));
323 Store(MachineRepresentation::kTagged, elements, offset, value);
324 MaybeUpdateLengthAndReturn(receiver, intptr_index, value,
325 update_length);
326 }
327 }
328 }
329
330 Bind(&check_double_elements);
331 Node* fixed_double_array_map = LoadRoot(Heap::kFixedDoubleArrayMapRootIndex);
332 GotoIf(WordNotEqual(elements_map, fixed_double_array_map),
333 &check_cow_elements);
334 // FixedDoubleArray backing store -> double elements.
335 {
336 Node* offset = ElementOffsetFromIndex(intptr_index, FAST_DOUBLE_ELEMENTS,
337 INTPTR_PARAMETERS, kHeaderSize);
338 // Check if we're about to overwrite the hole. We can safely do that
339 // only if there can be no setters on the prototype chain.
340 {
341 Label hole_check_passed(this);
342 // If we know that we're storing beyond the previous array length, we
343 // can skip the hole check (and always assume the hole).
344 if (update_length == kDontChangeLength) {
345 Label found_hole(this);
346 LoadDoubleWithHoleCheck(elements, offset, &found_hole,
347 MachineType::None());
348 Goto(&hole_check_passed);
349 Bind(&found_hole);
350 }
351 BranchIfPrototypesHaveNonFastElements(receiver_map, slow,
352 &hole_check_passed);
353 Bind(&hole_check_passed);
354 }
355
356 // Try to store the value as a double.
357 {
358 Label non_number_value(this);
359 Node* double_value = PrepareValueForWrite(value, Representation::Double(),
360 &non_number_value);
361 // Make sure we do not store signalling NaNs into double arrays.
362 double_value = Float64SilenceNaN(double_value);
363 // If we're about to introduce holes, ensure holey elements.
364 if (update_length == kBumpLengthWithGap) {
365 TryChangeToHoleyMap(receiver, receiver_map, elements_kind, context,
366 FAST_DOUBLE_ELEMENTS, slow);
367 }
368 StoreNoWriteBarrier(MachineRepresentation::kFloat64, elements, offset,
369 double_value);
370 MaybeUpdateLengthAndReturn(receiver, intptr_index, value, update_length);
371
372 Bind(&non_number_value);
373 }
374
375 // Transition to object elements.
376 {
377 Node* native_context = LoadNativeContext(context);
378 ElementsKind target_kind = update_length == kBumpLengthWithGap
379 ? FAST_HOLEY_ELEMENTS
380 : FAST_ELEMENTS;
381 TryRewriteElements(receiver, receiver_map, elements, native_context,
382 FAST_DOUBLE_ELEMENTS, target_kind, slow);
383 // Reload migrated elements.
384 Node* fast_elements = LoadElements(receiver);
385 Node* fast_offset = ElementOffsetFromIndex(
386 intptr_index, FAST_ELEMENTS, INTPTR_PARAMETERS, kHeaderSize);
387 Store(MachineRepresentation::kTagged, fast_elements, fast_offset, value);
388 MaybeUpdateLengthAndReturn(receiver, intptr_index, value, update_length);
389 }
390 }
391
392 Bind(&check_cow_elements);
393 {
394 // TODO(jkummerow): Use GrowElementsCapacity instead of bailing out.
395 Goto(slow);
396 }
397 }
398
399 void KeyedStoreGenericAssembler::EmitGenericElementStore(
400 Node* receiver, Node* receiver_map, Node* instance_type, Node* intptr_index,
401 Node* value, Node* context, Label* slow) {
402 Label if_in_bounds(this), if_increment_length_by_one(this),
403 if_bump_length_with_gap(this), if_grow(this), if_nonfast(this),
404 if_typed_array(this), if_dictionary(this);
405 Node* elements = LoadElements(receiver);
406 Node* elements_kind = LoadMapElementsKind(receiver_map);
407 GotoIf(
408 Int32GreaterThan(elements_kind, Int32Constant(LAST_FAST_ELEMENTS_KIND)),
409 &if_nonfast);
410
411 Label if_array(this);
412 GotoIf(Word32Equal(instance_type, Int32Constant(JS_ARRAY_TYPE)), &if_array);
413 {
414 Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
415 Branch(UintPtrLessThan(intptr_index, capacity), &if_in_bounds, &if_grow);
416 }
417 Bind(&if_array);
418 {
419 Node* length = SmiUntag(LoadJSArrayLength(receiver));
420 GotoIf(UintPtrLessThan(intptr_index, length), &if_in_bounds);
421 Node* capacity = SmiUntag(LoadFixedArrayBaseLength(elements));
422 GotoIf(UintPtrGreaterThanOrEqual(intptr_index, capacity), &if_grow);
423 Branch(WordEqual(intptr_index, length), &if_increment_length_by_one,
424 &if_bump_length_with_gap);
425 }
426
427 Bind(&if_in_bounds);
428 {
429 StoreElementWithCapacity(receiver, receiver_map, elements, elements_kind,
430 intptr_index, value, context, slow,
431 kDontChangeLength);
432 }
433
434 Bind(&if_increment_length_by_one);
435 {
436 StoreElementWithCapacity(receiver, receiver_map, elements, elements_kind,
437 intptr_index, value, context, slow,
438 kIncrementLengthByOne);
439 }
440
441 Bind(&if_bump_length_with_gap);
442 {
443 StoreElementWithCapacity(receiver, receiver_map, elements, elements_kind,
444 intptr_index, value, context, slow,
445 kBumpLengthWithGap);
446 }
447
448 // Out-of-capacity accesses (index >= capacity) jump here. Additionally,
449 // an ElementsKind transition might be necessary.
450 Bind(&if_grow);
451 {
452 Comment("Grow backing store");
453 // TODO(jkummerow): Support inline backing store growth.
454 Goto(slow);
455 }
456
457 // Any ElementsKind > LAST_FAST_ELEMENTS_KIND jumps here for further dispatch.
458 Bind(&if_nonfast);
459 {
460 STATIC_ASSERT(LAST_ELEMENTS_KIND == LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
461 GotoIf(Int32GreaterThanOrEqual(
462 elements_kind,
463 Int32Constant(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND)),
464 &if_typed_array);
465 GotoIf(Word32Equal(elements_kind, Int32Constant(DICTIONARY_ELEMENTS)),
466 &if_dictionary);
467 Goto(slow);
468 }
469
470 Bind(&if_dictionary);
471 {
472 Comment("Dictionary");
473 // TODO(jkummerow): Support storing to dictionary elements.
474 Goto(slow);
475 }
476
477 Bind(&if_typed_array);
478 {
479 Comment("Typed array");
480 // TODO(jkummerow): Support typed arrays.
481 Goto(slow);
482 }
483 }
484
485 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
486 Node* receiver, Node* receiver_map, const StoreICParameters* p,
487 Label* slow) {
488 Comment("stub cache probe");
489 // TODO(jkummerow): Don't rely on the stub cache as much.
490 // - existing properties can be overwritten inline (unless readonly).
491 // - for dictionary mode receivers, we can even add properties inline
492 // (unless the prototype chain prevents it).
493 Variable var_handler(this, MachineRepresentation::kTagged);
494 Label found_handler(this, &var_handler), stub_cache_miss(this);
495 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name,
496 &found_handler, &var_handler, &stub_cache_miss);
497 Bind(&found_handler);
498 {
499 Comment("KeyedStoreGeneric found handler");
500 HandleStoreICHandlerCase(p, var_handler.value(), slow);
501 }
502 Bind(&stub_cache_miss);
503 {
504 Comment("KeyedStoreGeneric_miss");
505 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot,
506 p->vector, p->receiver, p->name);
507 }
508 }
509
510 void KeyedStoreGenericAssembler::KeyedStoreGeneric(const StoreICParameters* p,
511 LanguageMode language_mode) {
512 Variable var_index(this, MachineType::PointerRepresentation());
513 Label if_index(this), if_unique_name(this), slow(this);
514
515 Node* receiver = p->receiver;
516 GotoIf(TaggedIsSmi(receiver), &slow);
517 Node* receiver_map = LoadMap(receiver);
518 Node* instance_type = LoadMapInstanceType(receiver_map);
519 // Receivers requiring non-standard element accesses (interceptors, access
520 // checks, strings and string wrappers, proxies) are handled in the runtime.
521 GotoIf(Int32LessThanOrEqual(instance_type,
522 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
523 &slow);
524
525 TryToName(p->name, &if_index, &var_index, &if_unique_name, &slow);
526
527 Bind(&if_index);
528 {
529 Comment("integer index");
530 EmitGenericElementStore(receiver, receiver_map, instance_type,
531 var_index.value(), p->value, p->context, &slow);
532 }
533
534 Bind(&if_unique_name);
535 {
536 Comment("key is unique name");
537 EmitGenericPropertyStore(receiver, receiver_map, p, &slow);
538 }
539
540 Bind(&slow);
541 {
542 Comment("KeyedStoreGeneric_slow");
543 TailCallRuntime(Runtime::kSetProperty, p->context, p->receiver, p->name,
544 p->value, SmiConstant(language_mode));
545 }
546 }
547
548 } // namespace internal
549 } // namespace v8
OLDNEW
« no previous file with comments | « src/ic/keyed-store-generic.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698