V8 Project
ic-x64.cc
Go to the documentation of this file.
1 // Copyright 2012 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/v8.h"
6 
7 #if V8_TARGET_ARCH_X64
8 
9 #include "src/codegen.h"
10 #include "src/ic/ic.h"
11 #include "src/ic/ic-compiler.h"
12 #include "src/ic/stub-cache.h"
13 
14 namespace v8 {
15 namespace internal {
16 
17 // ----------------------------------------------------------------------------
18 // Static IC stub generators.
19 //
20 
21 #define __ ACCESS_MASM(masm)
22 
23 
24 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
25  Label* global_object) {
26  // Register usage:
27  // type: holds the receiver instance type on entry.
28  __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE));
29  __ j(equal, global_object);
30  __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE));
31  __ j(equal, global_object);
32  __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
33  __ j(equal, global_object);
34 }
35 
36 
37 // Helper function used to load a property from a dictionary backing storage.
38 // This function may return false negatives, so miss_label
39 // must always call a backup property load that is complete.
40 // This function is safe to call if name is not an internalized string,
41 // and will jump to the miss_label in that case.
42 // The generated code assumes that the receiver has slow properties,
43 // is not a global object and does not have interceptors.
44 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
45  Register elements, Register name,
46  Register r0, Register r1, Register result) {
47  // Register use:
48  //
49  // elements - holds the property dictionary on entry and is unchanged.
50  //
51  // name - holds the name of the property on entry and is unchanged.
52  //
53  // r0 - used to hold the capacity of the property dictionary.
54  //
55  // r1 - used to hold the index into the property dictionary.
56  //
57  // result - holds the result on exit if the load succeeded.
58 
59  Label done;
60 
61  // Probe the dictionary.
63  elements, name, r0, r1);
64 
65  // If probing finds an entry in the dictionary, r1 contains the
66  // index into the dictionary. Check that the value is a normal
67  // property.
68  __ bind(&done);
69  const int kElementsStartOffset =
72  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
73  __ Test(Operand(elements, r1, times_pointer_size,
74  kDetailsOffset - kHeapObjectTag),
75  Smi::FromInt(PropertyDetails::TypeField::kMask));
76  __ j(not_zero, miss_label);
77 
78  // Get the value at the masked, scaled index.
79  const int kValueOffset = kElementsStartOffset + kPointerSize;
80  __ movp(result, Operand(elements, r1, times_pointer_size,
81  kValueOffset - kHeapObjectTag));
82 }
83 
84 
85 // Helper function used to store a property to a dictionary backing
86 // storage. This function may fail to store a property even though it
87 // is in the dictionary, so code at miss_label must always call a
88 // backup property store that is complete. This function is safe to
89 // call if name is not an internalized string, and will jump to the miss_label
90 // in that case. The generated code assumes that the receiver has slow
91 // properties, is not a global object and does not have interceptors.
92 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss_label,
93  Register elements, Register name,
94  Register value, Register scratch0,
95  Register scratch1) {
96  // Register use:
97  //
98  // elements - holds the property dictionary on entry and is clobbered.
99  //
100  // name - holds the name of the property on entry and is unchanged.
101  //
102  // value - holds the value to store and is unchanged.
103  //
104  // scratch0 - used during the positive dictionary lookup and is clobbered.
105  //
106  // scratch1 - used for index into the property dictionary and is clobbered.
107  Label done;
108 
109  // Probe the dictionary.
111  masm, miss_label, &done, elements, name, scratch0, scratch1);
112 
113  // If probing finds an entry in the dictionary, scratch0 contains the
114  // index into the dictionary. Check that the value is a normal
115  // property that is not read only.
116  __ bind(&done);
117  const int kElementsStartOffset =
120  const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
121  const int kTypeAndReadOnlyMask =
122  (PropertyDetails::TypeField::kMask |
123  PropertyDetails::AttributesField::encode(READ_ONLY))
124  << kSmiTagSize;
125  __ Test(Operand(elements, scratch1, times_pointer_size,
126  kDetailsOffset - kHeapObjectTag),
127  Smi::FromInt(kTypeAndReadOnlyMask));
128  __ j(not_zero, miss_label);
129 
130  // Store the value at the masked, scaled index.
131  const int kValueOffset = kElementsStartOffset + kPointerSize;
132  __ leap(scratch1, Operand(elements, scratch1, times_pointer_size,
133  kValueOffset - kHeapObjectTag));
134  __ movp(Operand(scratch1, 0), value);
135 
136  // Update write barrier. Make sure not to clobber the value.
137  __ movp(scratch0, value);
138  __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs);
139 }
140 
141 
142 // Checks the receiver for special cases (value type, slow case bits).
143 // Falls through for regular JS object.
144 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
145  Register receiver, Register map,
146  int interceptor_bit, Label* slow) {
147  // Register use:
148  // receiver - holds the receiver and is unchanged.
149  // Scratch registers:
150  // map - used to hold the map of the receiver.
151 
152  // Check that the object isn't a smi.
153  __ JumpIfSmi(receiver, slow);
154 
155  // Check that the object is some kind of JS object EXCEPT JS Value type.
156  // In the case that the object is a value-wrapper object,
157  // we enter the runtime system to make sure that indexing
158  // into string objects work as intended.
160  __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
161  __ j(below, slow);
162 
163  // Check bit field.
164  __ testb(
166  Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
167  __ j(not_zero, slow);
168 }
169 
170 
171 // Loads an indexed element from a fast case array.
172 // If not_fast_array is NULL, doesn't perform the elements map check.
173 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
174  Register key, Register elements,
175  Register scratch, Register result,
176  Label* not_fast_array, Label* out_of_range) {
177  // Register use:
178  //
179  // receiver - holds the receiver on entry.
180  // Unchanged unless 'result' is the same register.
181  //
182  // key - holds the smi key on entry.
183  // Unchanged unless 'result' is the same register.
184  //
185  // elements - holds the elements of the receiver on exit.
186  //
187  // result - holds the result on exit if the load succeeded.
188  // Allowed to be the the same as 'receiver' or 'key'.
189  // Unchanged on bailout so 'receiver' and 'key' can be safely
190  // used by further computation.
191  //
192  // Scratch registers:
193  //
194  // scratch - used to hold elements of the receiver and the loaded value.
195 
196  __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset));
197  if (not_fast_array != NULL) {
198  // Check that the object is in fast mode and writable.
199  __ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
200  Heap::kFixedArrayMapRootIndex);
201  __ j(not_equal, not_fast_array);
202  } else {
203  __ AssertFastElements(elements);
204  }
205  // Check that the key (index) is within bounds.
206  __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
207  // Unsigned comparison rejects negative indices.
208  __ j(above_equal, out_of_range);
209  // Fast case: Do the load.
210  SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
211  __ movp(scratch, FieldOperand(elements, index.reg, index.scale,
213  __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
214  // In case the loaded value is the_hole we have to consult GetProperty
215  // to ensure the prototype chain is searched.
216  __ j(equal, out_of_range);
217  if (!result.is(scratch)) {
218  __ movp(result, scratch);
219  }
220 }
221 
222 
223 // Checks whether a key is an array index string or a unique name.
224 // Falls through if the key is a unique name.
225 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
226  Register map, Register hash,
227  Label* index_string, Label* not_unique) {
228  // Register use:
229  // key - holds the key and is unchanged. Assumed to be non-smi.
230  // Scratch registers:
231  // map - used to hold the map of the key.
232  // hash - used to hold the hash of the key.
233  Label unique;
234  __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
235  __ j(above, not_unique);
237  __ j(equal, &unique);
238 
239  // Is the string an array index, with cached numeric value?
240  __ movl(hash, FieldOperand(key, Name::kHashFieldOffset));
241  __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask));
242  __ j(zero, index_string); // The value in hash is used at jump target.
243 
244  // Is the string internalized? We already know it's a string so a single
245  // bit test is enough.
248  Immediate(kIsNotInternalizedMask));
249  __ j(not_zero, not_unique);
250 
251  __ bind(&unique);
252 }
253 
254 
255 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
256  // The return address is on the stack.
257  Label slow, check_name, index_smi, index_name, property_array_property;
258  Label probe_dictionary, check_number_dictionary;
259 
260  Register receiver = LoadDescriptor::ReceiverRegister();
261  Register key = LoadDescriptor::NameRegister();
262  DCHECK(receiver.is(rdx));
263  DCHECK(key.is(rcx));
264 
265  // Check that the key is a smi.
266  __ JumpIfNotSmi(key, &check_name);
267  __ bind(&index_smi);
268  // Now the key is known to be a smi. This place is also jumped to from below
269  // where a numeric string is converted to a smi.
270 
271  GenerateKeyedLoadReceiverCheck(masm, receiver, rax,
273 
274  // Check the receiver's map to see if it has fast elements.
275  __ CheckFastElements(rax, &check_number_dictionary);
276 
277  GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, NULL, &slow);
278  Counters* counters = masm->isolate()->counters();
279  __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
280  __ ret(0);
281 
282  __ bind(&check_number_dictionary);
283  __ SmiToInteger32(rbx, key);
284  __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
285 
286  // Check whether the elements is a number dictionary.
287  // rbx: key as untagged int32
288  // rax: elements
290  Heap::kHashTableMapRootIndex);
291  __ j(not_equal, &slow);
292  __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
293  __ ret(0);
294 
295  __ bind(&slow);
296  // Slow case: Jump to runtime.
297  __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
299 
300  __ bind(&check_name);
301  GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
302 
303  GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor,
304  &slow);
305 
306  // If the receiver is a fast-case object, check the keyed lookup
307  // cache. Otherwise probe the dictionary leaving result in key.
310  Heap::kHashTableMapRootIndex);
311  __ j(equal, &probe_dictionary);
312 
313  // Load the map of the receiver, compute the keyed lookup cache hash
314  // based on 32 bits of the map pointer and the string hash.
315  __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
316  __ movl(rax, rbx);
317  __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift));
319  __ shrl(rdi, Immediate(String::kHashShift));
320  __ xorp(rax, rdi);
322  __ andp(rax, Immediate(mask));
323 
324  // Load the key (consisting of map and internalized string) from the cache and
325  // check for match.
326  Label load_in_object_property;
327  static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
328  Label hit_on_nth_entry[kEntriesPerBucket];
329  ExternalReference cache_keys =
330  ExternalReference::keyed_lookup_cache_keys(masm->isolate());
331 
332  for (int i = 0; i < kEntriesPerBucket - 1; i++) {
333  Label try_next_entry;
334  __ movp(rdi, rax);
335  __ shlp(rdi, Immediate(kPointerSizeLog2 + 1));
336  __ LoadAddress(kScratchRegister, cache_keys);
337  int off = kPointerSize * i * 2;
338  __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
339  __ j(not_equal, &try_next_entry);
340  __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
341  __ j(equal, &hit_on_nth_entry[i]);
342  __ bind(&try_next_entry);
343  }
344 
345  int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
346  __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
347  __ j(not_equal, &slow);
348  __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
349  __ j(not_equal, &slow);
350 
351  // Get field offset, which is a 32-bit integer.
352  ExternalReference cache_field_offsets =
353  ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
354 
355  // Hit on nth entry.
356  for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
357  __ bind(&hit_on_nth_entry[i]);
358  if (i != 0) {
359  __ addl(rax, Immediate(i));
360  }
361  __ LoadAddress(kScratchRegister, cache_field_offsets);
362  __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0));
364  __ subp(rdi, rax);
365  __ j(above_equal, &property_array_property);
366  if (i != 0) {
367  __ jmp(&load_in_object_property);
368  }
369  }
370 
371  // Load in-object property.
372  __ bind(&load_in_object_property);
374  __ addp(rax, rdi);
375  __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0));
376  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
377  __ ret(0);
378 
379  // Load property array property.
380  __ bind(&property_array_property);
382  __ movp(rax,
384  __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
385  __ ret(0);
386 
387  // Do a quick inline probe of the receiver's dictionary, if it
388  // exists.
389  __ bind(&probe_dictionary);
390  // rbx: elements
391 
392  __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset));
394  GenerateGlobalInstanceTypeCheck(masm, rax, &slow);
395 
396  GenerateDictionaryLoad(masm, &slow, rbx, key, rax, rdi, rax);
397  __ IncrementCounter(counters->keyed_load_generic_symbol(), 1);
398  __ ret(0);
399 
400  __ bind(&index_name);
401  __ IndexFromHash(rbx, key);
402  __ jmp(&index_smi);
403 }
404 
405 
406 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
407  // Return address is on the stack.
408  Label miss;
409 
410  Register receiver = LoadDescriptor::ReceiverRegister();
411  Register index = LoadDescriptor::NameRegister();
412  Register scratch = rbx;
413  Register result = rax;
414  DCHECK(!scratch.is(receiver) && !scratch.is(index));
415 
416  StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
417  &miss, // When not a string.
418  &miss, // When not a number.
419  &miss, // When index out of range.
421  char_at_generator.GenerateFast(masm);
422  __ ret(0);
423 
424  StubRuntimeCallHelper call_helper;
425  char_at_generator.GenerateSlow(masm, call_helper);
426 
427  __ bind(&miss);
428  GenerateMiss(masm);
429 }
430 
431 
432 static void KeyedStoreGenerateGenericHelper(
433  MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
434  KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) {
435  Label transition_smi_elements;
436  Label finish_object_store, non_double_value, transition_double_elements;
437  Label fast_double_without_map_check;
438  Register receiver = StoreDescriptor::ReceiverRegister();
439  Register key = StoreDescriptor::NameRegister();
440  Register value = StoreDescriptor::ValueRegister();
441  DCHECK(receiver.is(rdx));
442  DCHECK(key.is(rcx));
443  DCHECK(value.is(rax));
444  // Fast case: Do the store, could be either Object or double.
445  __ bind(fast_object);
446  // rbx: receiver's elements array (a FixedArray)
447  // receiver is a JSArray.
448  // r9: map of receiver
449  if (check_map == kCheckMap) {
451  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
452  __ j(not_equal, fast_double);
453  }
454 
455  // HOLECHECK: guards "A[i] = V"
456  // We have to go to the runtime if the current value is the hole because
457  // there may be a callback on the element
458  Label holecheck_passed1;
459  __ movp(kScratchRegister,
461  __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
462  __ j(not_equal, &holecheck_passed1);
463  __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
464 
465  __ bind(&holecheck_passed1);
466 
467  // Smi stores don't require further checks.
468  Label non_smi_value;
469  __ JumpIfNotSmi(value, &non_smi_value);
470  if (increment_length == kIncrementLength) {
471  // Add 1 to receiver->length.
472  __ leal(rdi, Operand(key, 1));
473  __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
474  }
475  // It's irrelevant whether array is smi-only or not when writing a smi.
477  value);
478  __ ret(0);
479 
480  __ bind(&non_smi_value);
481  // Writing a non-smi, check whether array allows non-smi elements.
482  // r9: receiver's map
483  __ CheckFastObjectElements(r9, &transition_smi_elements);
484 
485  __ bind(&finish_object_store);
486  if (increment_length == kIncrementLength) {
487  // Add 1 to receiver->length.
488  __ leal(rdi, Operand(key, 1));
489  __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
490  }
492  value);
493  __ movp(rdx, value); // Preserve the value which is returned.
494  __ RecordWriteArray(rbx, rdx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
496  __ ret(0);
497 
498  __ bind(fast_double);
499  if (check_map == kCheckMap) {
500  // Check for fast double array case. If this fails, call through to the
501  // runtime.
502  // rdi: elements array's map
503  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
504  __ j(not_equal, slow);
505  }
506 
507  // HOLECHECK: guards "A[i] double hole?"
508  // We have to see if the double version of the hole is present. If so
509  // go to the runtime.
511  __ cmpl(FieldOperand(rbx, key, times_8, offset), Immediate(kHoleNanUpper32));
512  __ j(not_equal, &fast_double_without_map_check);
513  __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
514 
515  __ bind(&fast_double_without_map_check);
516  __ StoreNumberToDoubleElements(value, rbx, key, xmm0,
517  &transition_double_elements);
518  if (increment_length == kIncrementLength) {
519  // Add 1 to receiver->length.
520  __ leal(rdi, Operand(key, 1));
521  __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
522  }
523  __ ret(0);
524 
525  __ bind(&transition_smi_elements);
526  __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
527 
528  // Transition the array appropriately depending on the value type.
529  __ movp(r9, FieldOperand(value, HeapObject::kMapOffset));
530  __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex);
531  __ j(not_equal, &non_double_value);
532 
533  // Value is a double. Transition FAST_SMI_ELEMENTS ->
534  // FAST_DOUBLE_ELEMENTS and complete the store.
535  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
536  FAST_DOUBLE_ELEMENTS, rbx, rdi, slow);
539  ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
540  rbx, mode, slow);
541  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
542  __ jmp(&fast_double_without_map_check);
543 
544  __ bind(&non_double_value);
545  // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
546  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, rbx,
547  rdi, slow);
550  masm, receiver, key, value, rbx, mode, slow);
551  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
552  __ jmp(&finish_object_store);
553 
554  __ bind(&transition_double_elements);
555  // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
556  // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
557  // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
558  __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
559  __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
560  rbx, rdi, slow);
563  value, rbx, mode, slow);
564  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
565  __ jmp(&finish_object_store);
566 }
567 
568 
569 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
570  StrictMode strict_mode) {
571  // Return address is on the stack.
572  Label slow, slow_with_tagged_index, fast_object, fast_object_grow;
573  Label fast_double, fast_double_grow;
574  Label array, extra, check_if_double_array;
575  Register receiver = StoreDescriptor::ReceiverRegister();
576  Register key = StoreDescriptor::NameRegister();
577  DCHECK(receiver.is(rdx));
578  DCHECK(key.is(rcx));
579 
580  // Check that the object isn't a smi.
581  __ JumpIfSmi(receiver, &slow_with_tagged_index);
582  // Get the map from the receiver.
583  __ movp(r9, FieldOperand(receiver, HeapObject::kMapOffset));
584  // Check that the receiver does not require access checks and is not observed.
585  // The generic stub does not perform map checks or handle observed objects.
587  Immediate(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved));
588  __ j(not_zero, &slow_with_tagged_index);
589  // Check that the key is a smi.
590  __ JumpIfNotSmi(key, &slow_with_tagged_index);
591  __ SmiToInteger32(key, key);
592 
593  __ CmpInstanceType(r9, JS_ARRAY_TYPE);
594  __ j(equal, &array);
595  // Check that the object is some kind of JSObject.
596  __ CmpInstanceType(r9, FIRST_JS_OBJECT_TYPE);
597  __ j(below, &slow);
598 
599  // Object case: Check key against length in the elements array.
600  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
601  // Check array bounds.
602  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key);
603  // rbx: FixedArray
604  __ j(above, &fast_object);
605 
606  // Slow case: call runtime.
607  __ bind(&slow);
608  __ Integer32ToSmi(key, key);
609  __ bind(&slow_with_tagged_index);
611  // Never returns to here.
612 
613  // Extra capacity case: Check if there is extra capacity to
614  // perform the store and update the length. Used for adding one
615  // element to the array by writing to array[array.length].
616  __ bind(&extra);
617  // receiver is a JSArray.
618  // rbx: receiver's elements array (a FixedArray)
619  // flags: smicompare (receiver.length(), rbx)
620  __ j(not_equal, &slow); // do not leave holes in the array
621  __ SmiCompareInteger32(FieldOperand(rbx, FixedArray::kLengthOffset), key);
622  __ j(below_equal, &slow);
623  // Increment index to get new length.
625  __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
626  __ j(not_equal, &check_if_double_array);
627  __ jmp(&fast_object_grow);
628 
629  __ bind(&check_if_double_array);
630  // rdi: elements array's map
631  __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
632  __ j(not_equal, &slow);
633  __ jmp(&fast_double_grow);
634 
635  // Array case: Get the length and the elements array from the JS
636  // array. Check that the array is in fast mode (and writable); if it
637  // is the length is always a smi.
638  __ bind(&array);
639  // receiver is a JSArray.
640  __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
641 
642  // Check the key against the length in the array, compute the
643  // address to store into and fall through to fast case.
644  __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key);
645  __ j(below_equal, &extra);
646 
647  KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
649  KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
651 }
652 
653 
654 static Operand GenerateMappedArgumentsLookup(
655  MacroAssembler* masm, Register object, Register key, Register scratch1,
656  Register scratch2, Register scratch3, Label* unmapped_case,
657  Label* slow_case) {
658  Heap* heap = masm->isolate()->heap();
659 
660  // Check that the receiver is a JSObject. Because of the elements
661  // map check later, we do not need to check for interceptors or
662  // whether it requires access checks.
663  __ JumpIfSmi(object, slow_case);
664  // Check that the object is some kind of JSObject.
665  __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
666  __ j(below, slow_case);
667 
668  // Check that the key is a positive smi.
669  Condition check = masm->CheckNonNegativeSmi(key);
670  __ j(NegateCondition(check), slow_case);
671 
672  // Load the elements into scratch1 and check its map. If not, jump
673  // to the unmapped lookup with the parameter map in scratch1.
674  Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
675  __ movp(scratch1, FieldOperand(object, JSObject::kElementsOffset));
676  __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
677 
678  // Check if element is in the range of mapped arguments.
679  __ movp(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
680  __ SmiSubConstant(scratch2, scratch2, Smi::FromInt(2));
681  __ cmpp(key, scratch2);
682  __ j(greater_equal, unmapped_case);
683 
684  // Load element index and check whether it is the hole.
685  const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
686  __ SmiToInteger64(scratch3, key);
687  __ movp(scratch2,
688  FieldOperand(scratch1, scratch3, times_pointer_size, kHeaderSize));
689  __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex);
690  __ j(equal, unmapped_case);
691 
692  // Load value from context and return it. We can reuse scratch1 because
693  // we do not jump to the unmapped lookup (which requires the parameter
694  // map in scratch1).
695  __ movp(scratch1, FieldOperand(scratch1, FixedArray::kHeaderSize));
696  __ SmiToInteger64(scratch3, scratch2);
697  return FieldOperand(scratch1, scratch3, times_pointer_size,
699 }
700 
701 
702 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
703  Register key,
704  Register parameter_map,
705  Register scratch,
706  Label* slow_case) {
707  // Element is in arguments backing store, which is referenced by the
708  // second element of the parameter_map. The parameter_map register
709  // must be loaded with the parameter map of the arguments object and is
710  // overwritten.
711  const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
712  Register backing_store = parameter_map;
713  __ movp(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
714  Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
715  __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
716  __ movp(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
717  __ cmpp(key, scratch);
718  __ j(greater_equal, slow_case);
719  __ SmiToInteger64(scratch, key);
720  return FieldOperand(backing_store, scratch, times_pointer_size,
722 }
723 
724 
725 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
726  // The return address is on the stack.
727  Label slow, notin;
728  Register receiver = StoreDescriptor::ReceiverRegister();
729  Register name = StoreDescriptor::NameRegister();
730  Register value = StoreDescriptor::ValueRegister();
731  DCHECK(receiver.is(rdx));
732  DCHECK(name.is(rcx));
733  DCHECK(value.is(rax));
734 
735  Operand mapped_location = GenerateMappedArgumentsLookup(
736  masm, receiver, name, rbx, rdi, r8, &notin, &slow);
737  __ movp(mapped_location, value);
738  __ leap(r9, mapped_location);
739  __ movp(r8, value);
740  __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
742  __ Ret();
743  __ bind(&notin);
744  // The unmapped lookup expects that the parameter map is in rbx.
745  Operand unmapped_location =
746  GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow);
747  __ movp(unmapped_location, value);
748  __ leap(r9, unmapped_location);
749  __ movp(r8, value);
750  __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
752  __ Ret();
753  __ bind(&slow);
754  GenerateMiss(masm);
755 }
756 
757 
758 void LoadIC::GenerateNormal(MacroAssembler* masm) {
759  Register dictionary = rax;
760  DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
761  DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
762 
763  Label slow;
764 
767  GenerateDictionaryLoad(masm, &slow, dictionary,
769  __ ret(0);
770 
771  // Dictionary load failed, go slow (but don't miss).
772  __ bind(&slow);
774 }
775 
776 
777 // A register that isn't one of the parameters to the load ic.
778 static const Register LoadIC_TempRegister() { return rbx; }
779 
780 
781 static const Register KeyedLoadIC_TempRegister() { return rbx; }
782 
783 
784 void LoadIC::GenerateMiss(MacroAssembler* masm) {
785  // The return address is on the stack.
786 
787  Counters* counters = masm->isolate()->counters();
788  __ IncrementCounter(counters->load_miss(), 1);
789 
790  __ PopReturnAddressTo(LoadIC_TempRegister());
793  __ PushReturnAddressFrom(LoadIC_TempRegister());
794 
795  // Perform tail call to the entry.
796  ExternalReference ref =
797  ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
798  __ TailCallExternalReference(ref, 2, 1);
799 }
800 
801 
802 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
803  // The return address is on the stack.
804 
805  __ PopReturnAddressTo(LoadIC_TempRegister());
808  __ PushReturnAddressFrom(LoadIC_TempRegister());
809 
810  // Perform tail call to the entry.
811  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
812 }
813 
814 
815 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
816  // The return address is on the stack.
817  Counters* counters = masm->isolate()->counters();
818  __ IncrementCounter(counters->keyed_load_miss(), 1);
819 
820  __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
823  __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
824 
825  // Perform tail call to the entry.
826  ExternalReference ref =
827  ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
828  __ TailCallExternalReference(ref, 2, 1);
829 }
830 
831 
832 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
833  // The return address is on the stack.
834 
835  __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
838  __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
839 
840  // Perform tail call to the entry.
841  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
842 }
843 
844 
845 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
846  // The return address is on the stack.
847 
848  // Get the receiver from the stack and probe the stub cache.
850  Code::ComputeHandlerFlags(Code::STORE_IC));
851  masm->isolate()->stub_cache()->GenerateProbe(
854 
855  // Cache miss: Jump to runtime.
856  GenerateMiss(masm);
857 }
858 
859 
860 static void StoreIC_PushArgs(MacroAssembler* masm) {
861  Register receiver = StoreDescriptor::ReceiverRegister();
862  Register name = StoreDescriptor::NameRegister();
863  Register value = StoreDescriptor::ValueRegister();
864 
865  DCHECK(!rbx.is(receiver) && !rbx.is(name) && !rbx.is(value));
866 
867  __ PopReturnAddressTo(rbx);
868  __ Push(receiver);
869  __ Push(name);
870  __ Push(value);
871  __ PushReturnAddressFrom(rbx);
872 }
873 
874 
875 void StoreIC::GenerateMiss(MacroAssembler* masm) {
876  // Return address is on the stack.
877  StoreIC_PushArgs(masm);
878 
879  // Perform tail call to the entry.
880  ExternalReference ref =
881  ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
882  __ TailCallExternalReference(ref, 3, 1);
883 }
884 
885 
886 void StoreIC::GenerateNormal(MacroAssembler* masm) {
887  Register receiver = StoreDescriptor::ReceiverRegister();
888  Register name = StoreDescriptor::NameRegister();
889  Register value = StoreDescriptor::ValueRegister();
890  Register dictionary = rbx;
891 
892  Label miss;
893 
894  __ movp(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset));
895  GenerateDictionaryStore(masm, &miss, dictionary, name, value, r8, r9);
896  Counters* counters = masm->isolate()->counters();
897  __ IncrementCounter(counters->store_normal_hit(), 1);
898  __ ret(0);
899 
900  __ bind(&miss);
901  __ IncrementCounter(counters->store_normal_miss(), 1);
902  GenerateMiss(masm);
903 }
904 
905 
906 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
907  // Return address is on the stack.
908  StoreIC_PushArgs(masm);
909 
910  // Do tail-call to runtime routine.
911  ExternalReference ref =
912  ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
913  __ TailCallExternalReference(ref, 3, 1);
914 }
915 
916 
917 #undef __
918 
919 
921  switch (op) {
922  case Token::EQ_STRICT:
923  case Token::EQ:
924  return equal;
925  case Token::LT:
926  return less;
927  case Token::GT:
928  return greater;
929  case Token::LTE:
930  return less_equal;
931  case Token::GTE:
932  return greater_equal;
933  default:
934  UNREACHABLE();
935  return no_condition;
936  }
937 }
938 
939 
941  // The address of the instruction following the call.
942  Address test_instruction_address =
944 
945  // If the instruction following the call is not a test al, nothing
946  // was inlined.
947  return *test_instruction_address == Assembler::kTestAlByte;
948 }
949 
950 
951 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) {
952  // The address of the instruction following the call.
953  Address test_instruction_address =
955 
956  // If the instruction following the call is not a test al, nothing
957  // was inlined.
958  if (*test_instruction_address != Assembler::kTestAlByte) {
959  DCHECK(*test_instruction_address == Assembler::kNopByte);
960  return;
961  }
962 
963  Address delta_address = test_instruction_address + 1;
964  // The delta to the start of the map check instruction and the
965  // condition code uses at the patched jump.
966  uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
967  if (FLAG_trace_ic) {
968  PrintF("[ patching ic at %p, test=%p, delta=%d\n", address,
969  test_instruction_address, delta);
970  }
971 
972  // Patch with a short conditional jump. Enabling means switching from a short
973  // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
974  // reverse operation of that.
975  Address jmp_address = test_instruction_address - delta;
977  ? (*jmp_address == Assembler::kJncShortOpcode ||
978  *jmp_address == Assembler::kJcShortOpcode)
979  : (*jmp_address == Assembler::kJnzShortOpcode ||
980  *jmp_address == Assembler::kJzShortOpcode));
981  Condition cc =
982  (check == ENABLE_INLINED_SMI_CHECK)
983  ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
984  : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
985  *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
986 }
987 }
988 } // namespace v8::internal
989 
990 #endif // V8_TARGET_ARCH_X64
static AllocationSiteMode GetMode(ElementsKind boilerplate_elements_kind)
Definition: objects-inl.h:1591
static const byte kJnzShortOpcode
static const byte kNopByte
static const byte kJccShortPrefix
static const byte kJncShortOpcode
static const byte kTestAlByte
static const int kCallTargetAddressOffset
static const byte kJcShortOpcode
static const byte kJzShortOpcode
static Flags ComputeHandlerFlags(Kind handler_kind, StubType type=NORMAL, CacheHolderFlag holder=kCacheOnReceiver)
Definition: objects-inl.h:4975
static Flags RemoveTypeAndHolderFromFlags(Flags flags)
Definition: objects-inl.h:5012
uint32_t Flags
Definition: objects.h:4929
static bool HasInlinedSmiCode(Address address)
static Condition ComputeCondition(Token::Value op)
static void GenerateSmiToDouble(MacroAssembler *masm, Register receiver, Register key, Register value, Register target_map, AllocationSiteMode mode, Label *fail)
static void GenerateMapChangeElementsTransition(MacroAssembler *masm, Register receiver, Register key, Register value, Register target_map, AllocationSiteMode mode, Label *allocation_memento_found)
static void GenerateDoubleToObject(MacroAssembler *masm, Register receiver, Register key, Register value, Register target_map, AllocationSiteMode mode, Label *fail)
static const int kLengthOffset
Definition: objects.h:2392
static const int kHeaderSize
Definition: objects.h:2393
static const int kElementsStartIndex
Definition: objects.h:3274
static const int kMapOffset
Definition: objects.h:1427
Address address() const
Definition: ic-inl.h:19
static const int kLengthOffset
Definition: objects.h:10072
static const int kPropertiesOffset
Definition: objects.h:2193
static const int kElementsOffset
Definition: objects.h:2194
static void GenerateMiss(MacroAssembler *masm)
static void GenerateString(MacroAssembler *masm)
static void GenerateRuntimeGetProperty(MacroAssembler *masm)
static void GenerateGeneric(MacroAssembler *masm)
static const int kHashMask
Definition: heap.h:2255
static const int kCapacityMask
Definition: heap.h:2253
static const int kMapHashShift
Definition: heap.h:2254
static const int kEntriesPerBucket
Definition: heap.h:2256
static void GenerateMiss(MacroAssembler *masm)
static void GenerateSloppyArguments(MacroAssembler *masm)
static void GenerateGeneric(MacroAssembler *masm, StrictMode strict_mode)
static const Register ReceiverRegister()
static const Register NameRegister()
static void GenerateNormal(MacroAssembler *masm)
static void GenerateRuntimeGetProperty(MacroAssembler *masm)
static void GenerateMiss(MacroAssembler *masm)
static const int kHasIndexedInterceptor
Definition: objects.h:6243
static const int kBitFieldOffset
Definition: objects.h:6228
static const int kIsAccessCheckNeeded
Definition: objects.h:6246
static const int kInstanceTypeOffset
Definition: objects.h:6229
static const int kInstanceSizeOffset
Definition: objects.h:6210
static const int kInObjectPropertiesOffset
Definition: objects.h:6212
static const int kIsObserved
Definition: objects.h:6245
static const int kHasNamedInterceptor
Definition: objects.h:6242
static void GeneratePositiveLookup(MacroAssembler *masm, Label *miss, Label *done, Register elements, Register name, Register r0, Register r1)
static const int kHashShift
Definition: objects.h:8499
static const int kHashFieldOffset
Definition: objects.h:8486
static const unsigned int kContainsCachedArrayIndexMask
Definition: objects.h:8528
static void GenerateRuntimeSetProperty(MacroAssembler *masm, StrictMode strict_mode)
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register ValueRegister()
static void GenerateMiss(MacroAssembler *masm)
static void GenerateMegamorphic(MacroAssembler *masm)
StrictMode strict_mode() const
Definition: ic.h:465
static void GenerateNormal(MacroAssembler *masm)
#define __
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
Definition: scheduler.cc:773
const int kPointerSize
Definition: globals.h:129
@ DONT_DO_SMI_CHECK
Definition: globals.h:640
const Register kScratchRegister
const Register r0
const int kSmiTagSize
Definition: v8.h:5743
InlinedSmiCheck
Definition: ic.h:672
@ ENABLE_INLINED_SMI_CHECK
Definition: ic.h:672
Operand FieldOperand(Register object, int offset)
const uint32_t kNotInternalizedTag
Definition: objects.h:550
const int kPointerSizeLog2
Definition: globals.h:147
@ JS_VALUE_TYPE
Definition: objects.h:728
@ JS_GLOBAL_PROXY_TYPE
Definition: objects.h:737
@ JS_ARRAY_TYPE
Definition: objects.h:738
@ JS_OBJECT_TYPE
Definition: objects.h:731
@ FIRST_NONSTRING_TYPE
Definition: objects.h:758
@ FIRST_JS_RECEIVER_TYPE
Definition: objects.h:772
@ LAST_UNIQUE_NAME_TYPE
Definition: objects.h:757
@ FIRST_JS_OBJECT_TYPE
Definition: objects.h:775
@ JS_GLOBAL_OBJECT_TYPE
Definition: objects.h:735
@ JS_BUILTINS_OBJECT_TYPE
Definition: objects.h:736
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check)
const Register rdi
const Register r9
const XMMRegister xmm0
const Register rbx
Condition NegateCondition(Condition cond)
Definition: constants-arm.h:86
byte * Address
Definition: globals.h:101
const Register r8
const Register r1
void PrintF(const char *format,...)
Definition: utils.cc:80
const int kHeapObjectTag
Definition: v8.h:5737
const Register no_reg
const Register rdx
const Register rax
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const uint32_t kIsNotInternalizedMask
Definition: objects.h:549
const Register rcx
KeyedStoreCheckMap
Definition: ic.h:524
@ kDontCheckMap
Definition: ic.h:524
@ kCheckMap
Definition: ic.h:524
const uint32_t kHoleNanLower32
Definition: globals.h:657
@ STRING_INDEX_IS_ARRAY_INDEX
Definition: code-stubs.h:1595
const uint32_t kHoleNanUpper32
Definition: globals.h:656
KeyedStoreIncrementLength
Definition: ic.h:527
@ kDontIncrementLength
Definition: ic.h:527
@ kIncrementLength
Definition: ic.h:527
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
@ READ_ONLY
bool is(Register reg) const