V8 Project
ic-arm64.cc
Go to the documentation of this file.
1 // Copyright 2013 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_ARM64
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 #define __ ACCESS_MASM(masm)
19 
20 
21 // "type" holds an instance type on entry and is not clobbered.
22 // Generated code branch on "global_object" if type is any kind of global
23 // JS object.
24 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
25  Label* global_object) {
26  __ Cmp(type, JS_GLOBAL_OBJECT_TYPE);
27  __ Ccmp(type, JS_BUILTINS_OBJECT_TYPE, ZFlag, ne);
28  __ Ccmp(type, JS_GLOBAL_PROXY_TYPE, ZFlag, ne);
29  __ B(eq, global_object);
30 }
31 
32 
33 // Helper function used from LoadIC GenerateNormal.
34 //
35 // elements: Property dictionary. It is not clobbered if a jump to the miss
36 // label is done.
37 // name: Property name. It is not clobbered if a jump to the miss label is
38 // done
39 // result: Register for the result. It is only updated if a jump to the miss
40 // label is not done.
41 // The scratch registers need to be different from elements, name and result.
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,
45  Register elements, Register name,
46  Register result, Register scratch1,
47  Register scratch2) {
48  DCHECK(!AreAliased(elements, name, scratch1, scratch2));
49  DCHECK(!AreAliased(result, scratch1, scratch2));
50 
51  Label done;
52 
53  // Probe the dictionary.
54  NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements,
55  name, scratch1, scratch2);
56 
57  // If probing finds an entry check that the value is a normal property.
58  __ Bind(&done);
59 
60  static const int kElementsStartOffset =
63  static const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
64  __ Ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
65  __ Tst(scratch1, Smi::FromInt(PropertyDetails::TypeField::kMask));
66  __ B(ne, miss);
67 
68  // Get the value at the masked, scaled index and return.
69  __ Ldr(result,
70  FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize));
71 }
72 
73 
74 // Helper function used from StoreIC::GenerateNormal.
75 //
76 // elements: Property dictionary. It is not clobbered if a jump to the miss
77 // label is done.
78 // name: Property name. It is not clobbered if a jump to the miss label is
79 // done
80 // value: The value to store (never clobbered).
81 //
82 // The generated code assumes that the receiver has slow properties,
83 // is not a global object and does not have interceptors.
84 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss,
85  Register elements, Register name,
86  Register value, Register scratch1,
87  Register scratch2) {
88  DCHECK(!AreAliased(elements, name, value, scratch1, scratch2));
89 
90  Label done;
91 
92  // Probe the dictionary.
93  NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements,
94  name, scratch1, scratch2);
95 
96  // If probing finds an entry in the dictionary check that the value
97  // is a normal property that is not read only.
98  __ Bind(&done);
99 
100  static const int kElementsStartOffset =
103  static const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
104  static const int kTypeAndReadOnlyMask =
105  PropertyDetails::TypeField::kMask |
106  PropertyDetails::AttributesField::encode(READ_ONLY);
107  __ Ldrsw(scratch1, UntagSmiFieldMemOperand(scratch2, kDetailsOffset));
108  __ Tst(scratch1, kTypeAndReadOnlyMask);
109  __ B(ne, miss);
110 
111  // Store the value at the masked, scaled index and return.
112  static const int kValueOffset = kElementsStartOffset + kPointerSize;
113  __ Add(scratch2, scratch2, kValueOffset - kHeapObjectTag);
114  __ Str(value, MemOperand(scratch2));
115 
116  // Update the write barrier. Make sure not to clobber the value.
117  __ Mov(scratch1, value);
118  __ RecordWrite(elements, scratch2, scratch1, kLRHasNotBeenSaved,
120 }
121 
122 
123 // Checks the receiver for special cases (value type, slow case bits).
124 // Falls through for regular JS object and return the map of the
125 // receiver in 'map_scratch' if the receiver is not a SMI.
126 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
127  Register receiver,
128  Register map_scratch,
129  Register scratch,
130  int interceptor_bit, Label* slow) {
131  DCHECK(!AreAliased(map_scratch, scratch));
132 
133  // Check that the object isn't a smi.
134  __ JumpIfSmi(receiver, slow);
135  // Get the map of the receiver.
136  __ Ldr(map_scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
137  // Check bit field.
138  __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kBitFieldOffset));
139  __ Tbnz(scratch, Map::kIsAccessCheckNeeded, slow);
140  __ Tbnz(scratch, interceptor_bit, slow);
141 
142  // Check that the object is some kind of JS object EXCEPT JS Value type.
143  // In the case that the object is a value-wrapper object, we enter the
144  // runtime system to make sure that indexing into string objects work
145  // as intended.
147  __ Ldrb(scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset));
148  __ Cmp(scratch, JS_OBJECT_TYPE);
149  __ B(lt, slow);
150 }
151 
152 
153 // Loads an indexed element from a fast case array.
154 // If not_fast_array is NULL, doesn't perform the elements map check.
155 //
156 // receiver - holds the receiver on entry.
157 // Unchanged unless 'result' is the same register.
158 //
159 // key - holds the smi key on entry.
160 // Unchanged unless 'result' is the same register.
161 //
162 // elements - holds the elements of the receiver on exit.
163 //
164 // elements_map - holds the elements map on exit if the not_fast_array branch is
165 // taken. Otherwise, this is used as a scratch register.
166 //
167 // result - holds the result on exit if the load succeeded.
168 // Allowed to be the the same as 'receiver' or 'key'.
169 // Unchanged on bailout so 'receiver' and 'key' can be safely
170 // used by further computation.
171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
172  Register key, Register elements,
173  Register elements_map, Register scratch2,
174  Register result, Label* not_fast_array,
175  Label* slow) {
176  DCHECK(!AreAliased(receiver, key, elements, elements_map, scratch2));
177 
178  // Check for fast array.
179  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
180  if (not_fast_array != NULL) {
181  // Check that the object is in fast mode and writable.
182  __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
183  __ JumpIfNotRoot(elements_map, Heap::kFixedArrayMapRootIndex,
184  not_fast_array);
185  } else {
186  __ AssertFastElements(elements);
187  }
188 
189  // The elements_map register is only used for the not_fast_array path, which
190  // was handled above. From this point onward it is a scratch register.
191  Register scratch1 = elements_map;
192 
193  // Check that the key (index) is within bounds.
194  __ Ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
195  __ Cmp(key, scratch1);
196  __ B(hs, slow);
197 
198  // Fast case: Do the load.
199  __ Add(scratch1, elements, FixedArray::kHeaderSize - kHeapObjectTag);
200  __ SmiUntag(scratch2, key);
201  __ Ldr(scratch2, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2));
202 
203  // In case the loaded value is the_hole we have to consult GetProperty
204  // to ensure the prototype chain is searched.
205  __ JumpIfRoot(scratch2, Heap::kTheHoleValueRootIndex, slow);
206 
207  // Move the value to the result register.
208  // 'result' can alias with 'receiver' or 'key' but these two must be
209  // preserved if we jump to 'slow'.
210  __ Mov(result, scratch2);
211 }
212 
213 
214 // Checks whether a key is an array index string or a unique name.
215 // Falls through if a key is a unique name.
216 // The map of the key is returned in 'map_scratch'.
217 // If the jump to 'index_string' is done the hash of the key is left
218 // in 'hash_scratch'.
219 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
220  Register map_scratch, Register hash_scratch,
221  Label* index_string, Label* not_unique) {
222  DCHECK(!AreAliased(key, map_scratch, hash_scratch));
223 
224  // Is the key a name?
225  Label unique;
226  __ JumpIfObjectType(key, map_scratch, hash_scratch, LAST_UNIQUE_NAME_TYPE,
227  not_unique, hi);
229  __ B(eq, &unique);
230 
231  // Is the string an array index with cached numeric value?
232  __ Ldr(hash_scratch.W(), FieldMemOperand(key, Name::kHashFieldOffset));
233  __ TestAndBranchIfAllClear(hash_scratch, Name::kContainsCachedArrayIndexMask,
234  index_string);
235 
236  // Is the string internalized? We know it's a string, so a single bit test is
237  // enough.
238  __ Ldrb(hash_scratch, FieldMemOperand(map_scratch, Map::kInstanceTypeOffset));
240  __ TestAndBranchIfAnySet(hash_scratch, kIsNotInternalizedMask, not_unique);
241 
242  __ Bind(&unique);
243  // Fall through if the key is a unique name.
244 }
245 
246 
247 // Neither 'object' nor 'key' are modified by this function.
248 //
249 // If the 'unmapped_case' or 'slow_case' exit is taken, the 'map' register is
250 // left with the object's elements map. Otherwise, it is used as a scratch
251 // register.
252 static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm,
253  Register object, Register key,
254  Register map, Register scratch1,
255  Register scratch2,
256  Label* unmapped_case,
257  Label* slow_case) {
258  DCHECK(!AreAliased(object, key, map, scratch1, scratch2));
259 
260  Heap* heap = masm->isolate()->heap();
261 
262  // Check that the receiver is a JSObject. Because of the elements
263  // map check later, we do not need to check for interceptors or
264  // whether it requires access checks.
265  __ JumpIfSmi(object, slow_case);
266  // Check that the object is some kind of JSObject.
267  __ JumpIfObjectType(object, map, scratch1, FIRST_JS_RECEIVER_TYPE, slow_case,
268  lt);
269 
270  // Check that the key is a positive smi.
271  __ JumpIfNotSmi(key, slow_case);
272  __ Tbnz(key, kXSignBit, slow_case);
273 
274  // Load the elements object and check its map.
275  Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
277  __ CheckMap(map, scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
278 
279  // Check if element is in the range of mapped arguments. If not, jump
280  // to the unmapped lookup.
282  __ Sub(scratch1, scratch1, Smi::FromInt(2));
283  __ Cmp(key, scratch1);
284  __ B(hs, unmapped_case);
285 
286  // Load element index and check whether it is the hole.
287  static const int offset =
289 
290  __ Add(scratch1, map, offset);
291  __ SmiUntag(scratch2, key);
292  __ Ldr(scratch1, MemOperand(scratch1, scratch2, LSL, kPointerSizeLog2));
293  __ JumpIfRoot(scratch1, Heap::kTheHoleValueRootIndex, unmapped_case);
294 
295  // Load value from context and return it.
297  __ SmiUntag(scratch1);
298  __ Lsl(scratch1, scratch1, kPointerSizeLog2);
299  __ Add(scratch1, scratch1, Context::kHeaderSize - kHeapObjectTag);
300  // The base of the result (scratch2) is passed to RecordWrite in
301  // KeyedStoreIC::GenerateSloppyArguments and it must be a HeapObject.
302  return MemOperand(scratch2, scratch1);
303 }
304 
305 
306 // The 'parameter_map' register must be loaded with the parameter map of the
307 // arguments object and is overwritten.
308 static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
309  Register key,
310  Register parameter_map,
311  Register scratch,
312  Label* slow_case) {
313  DCHECK(!AreAliased(key, parameter_map, scratch));
314 
315  // Element is in arguments backing store, which is referenced by the
316  // second element of the parameter_map.
317  const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
318  Register backing_store = parameter_map;
319  __ Ldr(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset));
320  Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
321  __ CheckMap(backing_store, scratch, fixed_array_map, slow_case,
323  __ Ldr(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset));
324  __ Cmp(key, scratch);
325  __ B(hs, slow_case);
326 
327  __ Add(backing_store, backing_store,
329  __ SmiUntag(scratch, key);
330  return MemOperand(backing_store, scratch, LSL, kPointerSizeLog2);
331 }
332 
333 
334 void LoadIC::GenerateNormal(MacroAssembler* masm) {
335  Register dictionary = x0;
336  DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
337  DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
338  Label slow;
339 
342  GenerateDictionaryLoad(masm, &slow, dictionary,
343  LoadDescriptor::NameRegister(), x0, x3, x4);
344  __ Ret();
345 
346  // Dictionary load failed, go slow (but don't miss).
347  __ Bind(&slow);
349 }
350 
351 
352 void LoadIC::GenerateMiss(MacroAssembler* masm) {
353  // The return address is in lr.
354  Isolate* isolate = masm->isolate();
355  ASM_LOCATION("LoadIC::GenerateMiss");
356 
357  __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4);
358 
359  // Perform tail call to the entry.
361  ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
362  __ TailCallExternalReference(ref, 2, 1);
363 }
364 
365 
366 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
367  // The return address is in lr.
369  __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
370 }
371 
372 
373 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
374  ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments");
375  Label slow, notin;
376  Register value = StoreDescriptor::ValueRegister();
377  Register key = StoreDescriptor::NameRegister();
378  Register receiver = StoreDescriptor::ReceiverRegister();
379  DCHECK(receiver.is(x1));
380  DCHECK(key.is(x2));
381  DCHECK(value.is(x0));
382 
383  Register map = x3;
384 
385  // These registers are used by GenerateMappedArgumentsLookup to build a
386  // MemOperand. They are live for as long as the MemOperand is live.
387  Register mapped1 = x4;
388  Register mapped2 = x5;
389 
390  MemOperand mapped = GenerateMappedArgumentsLookup(
391  masm, receiver, key, map, mapped1, mapped2, &notin, &slow);
392  Operand mapped_offset = mapped.OffsetAsOperand();
393  __ Str(value, mapped);
394  __ Add(x10, mapped.base(), mapped_offset);
395  __ Mov(x11, value);
396  __ RecordWrite(mapped.base(), x10, x11, kLRHasNotBeenSaved, kDontSaveFPRegs);
397  __ Ret();
398 
399  __ Bind(&notin);
400 
401  // These registers are used by GenerateMappedArgumentsLookup to build a
402  // MemOperand. They are live for as long as the MemOperand is live.
403  Register unmapped1 = map; // This is assumed to alias 'map'.
404  Register unmapped2 = x4;
405  MemOperand unmapped =
406  GenerateUnmappedArgumentsLookup(masm, key, unmapped1, unmapped2, &slow);
407  Operand unmapped_offset = unmapped.OffsetAsOperand();
408  __ Str(value, unmapped);
409  __ Add(x10, unmapped.base(), unmapped_offset);
410  __ Mov(x11, value);
411  __ RecordWrite(unmapped.base(), x10, x11, kLRHasNotBeenSaved,
413  __ Ret();
414  __ Bind(&slow);
415  GenerateMiss(masm);
416 }
417 
418 
419 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
420  // The return address is in lr.
421  Isolate* isolate = masm->isolate();
422 
423  __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, x10, x11);
424 
426 
427  // Perform tail call to the entry.
428  ExternalReference ref =
429  ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
430 
431  __ TailCallExternalReference(ref, 2, 1);
432 }
433 
434 
435 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
436  // The return address is in lr.
438  __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
439 }
440 
441 
442 static void GenerateKeyedLoadWithSmiKey(MacroAssembler* masm, Register key,
443  Register receiver, Register scratch1,
444  Register scratch2, Register scratch3,
445  Register scratch4, Register scratch5,
446  Label* slow) {
447  DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4,
448  scratch5));
449 
450  Isolate* isolate = masm->isolate();
451  Label check_number_dictionary;
452  // If we can load the value, it should be returned in x0.
453  Register result = x0;
454 
455  GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2,
457 
458  // Check the receiver's map to see if it has fast elements.
459  __ CheckFastElements(scratch1, scratch2, &check_number_dictionary);
460 
461  GenerateFastArrayLoad(masm, receiver, key, scratch3, scratch2, scratch1,
462  result, NULL, slow);
463  __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1,
464  scratch1, scratch2);
465  __ Ret();
466 
467  __ Bind(&check_number_dictionary);
468  __ Ldr(scratch3, FieldMemOperand(receiver, JSObject::kElementsOffset));
469  __ Ldr(scratch2, FieldMemOperand(scratch3, JSObject::kMapOffset));
470 
471  // Check whether we have a number dictionary.
472  __ JumpIfNotRoot(scratch2, Heap::kHashTableMapRootIndex, slow);
473 
474  __ LoadFromNumberDictionary(slow, scratch3, key, result, scratch1, scratch2,
475  scratch4, scratch5);
476  __ Ret();
477 }
478 
479 static void GenerateKeyedLoadWithNameKey(MacroAssembler* masm, Register key,
480  Register receiver, Register scratch1,
481  Register scratch2, Register scratch3,
482  Register scratch4, Register scratch5,
483  Label* slow) {
484  DCHECK(!AreAliased(key, receiver, scratch1, scratch2, scratch3, scratch4,
485  scratch5));
486 
487  Isolate* isolate = masm->isolate();
488  Label probe_dictionary, property_array_property;
489  // If we can load the value, it should be returned in x0.
490  Register result = x0;
491 
492  GenerateKeyedLoadReceiverCheck(masm, receiver, scratch1, scratch2,
494 
495  // If the receiver is a fast-case object, check the keyed lookup cache.
496  // Otherwise probe the dictionary.
497  __ Ldr(scratch2, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
498  __ Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset));
499  __ JumpIfRoot(scratch3, Heap::kHashTableMapRootIndex, &probe_dictionary);
500 
501  // We keep the map of the receiver in scratch1.
502  Register receiver_map = scratch1;
503 
504  // Load the map of the receiver, compute the keyed lookup cache hash
505  // based on 32 bits of the map pointer and the name hash.
506  __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
507  __ Mov(scratch2, Operand(receiver_map, ASR, KeyedLookupCache::kMapHashShift));
508  __ Ldr(scratch3.W(), FieldMemOperand(key, Name::kHashFieldOffset));
509  __ Eor(scratch2, scratch2, Operand(scratch3, ASR, Name::kHashShift));
511  __ And(scratch2, scratch2, mask);
512 
513  // Load the key (consisting of map and unique name) from the cache and
514  // check for match.
515  Label load_in_object_property;
516  static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
517  Label hit_on_nth_entry[kEntriesPerBucket];
518  ExternalReference cache_keys =
519  ExternalReference::keyed_lookup_cache_keys(isolate);
520 
521  __ Mov(scratch3, cache_keys);
522  __ Add(scratch3, scratch3, Operand(scratch2, LSL, kPointerSizeLog2 + 1));
523 
524  for (int i = 0; i < kEntriesPerBucket - 1; i++) {
525  Label try_next_entry;
526  // Load map and make scratch3 pointing to the next entry.
527  __ Ldr(scratch4, MemOperand(scratch3, kPointerSize * 2, PostIndex));
528  __ Cmp(receiver_map, scratch4);
529  __ B(ne, &try_next_entry);
530  __ Ldr(scratch4, MemOperand(scratch3, -kPointerSize)); // Load name
531  __ Cmp(key, scratch4);
532  __ B(eq, &hit_on_nth_entry[i]);
533  __ Bind(&try_next_entry);
534  }
535 
536  // Last entry.
537  __ Ldr(scratch4, MemOperand(scratch3, kPointerSize, PostIndex));
538  __ Cmp(receiver_map, scratch4);
539  __ B(ne, slow);
540  __ Ldr(scratch4, MemOperand(scratch3));
541  __ Cmp(key, scratch4);
542  __ B(ne, slow);
543 
544  // Get field offset.
545  ExternalReference cache_field_offsets =
546  ExternalReference::keyed_lookup_cache_field_offsets(isolate);
547 
548  // Hit on nth entry.
549  for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
550  __ Bind(&hit_on_nth_entry[i]);
551  __ Mov(scratch3, cache_field_offsets);
552  if (i != 0) {
553  __ Add(scratch2, scratch2, i);
554  }
555  __ Ldr(scratch4.W(), MemOperand(scratch3, scratch2, LSL, 2));
556  __ Ldrb(scratch5,
558  __ Subs(scratch4, scratch4, scratch5);
559  __ B(ge, &property_array_property);
560  if (i != 0) {
561  __ B(&load_in_object_property);
562  }
563  }
564 
565  // Load in-object property.
566  __ Bind(&load_in_object_property);
567  __ Ldrb(scratch5, FieldMemOperand(receiver_map, Map::kInstanceSizeOffset));
568  __ Add(scratch5, scratch5, scratch4); // Index from start of object.
569  __ Sub(receiver, receiver, kHeapObjectTag); // Remove the heap tag.
570  __ Ldr(result, MemOperand(receiver, scratch5, LSL, kPointerSizeLog2));
571  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1,
572  scratch1, scratch2);
573  __ Ret();
574 
575  // Load property array property.
576  __ Bind(&property_array_property);
577  __ Ldr(scratch1, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
578  __ Add(scratch1, scratch1, FixedArray::kHeaderSize - kHeapObjectTag);
579  __ Ldr(result, MemOperand(scratch1, scratch4, LSL, kPointerSizeLog2));
580  __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1,
581  scratch1, scratch2);
582  __ Ret();
583 
584  // Do a quick inline probe of the receiver's dictionary, if it exists.
585  __ Bind(&probe_dictionary);
586  __ Ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
587  __ Ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
588  GenerateGlobalInstanceTypeCheck(masm, scratch1, slow);
589  // Load the property.
590  GenerateDictionaryLoad(masm, slow, scratch2, key, result, scratch1, scratch3);
591  __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), 1,
592  scratch1, scratch2);
593  __ Ret();
594 }
595 
596 
597 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
598  // The return address is in lr.
599  Label slow, check_name, index_smi, index_name;
600 
601  Register key = LoadDescriptor::NameRegister();
602  Register receiver = LoadDescriptor::ReceiverRegister();
603  DCHECK(key.is(x2));
604  DCHECK(receiver.is(x1));
605 
606  __ JumpIfNotSmi(key, &check_name);
607  __ Bind(&index_smi);
608  // Now the key is known to be a smi. This place is also jumped to from below
609  // where a numeric string is converted to a smi.
610  GenerateKeyedLoadWithSmiKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
611 
612  // Slow case.
613  __ Bind(&slow);
614  __ IncrementCounter(masm->isolate()->counters()->keyed_load_generic_slow(), 1,
615  x4, x3);
617 
618  __ Bind(&check_name);
619  GenerateKeyNameCheck(masm, key, x0, x3, &index_name, &slow);
620 
621  GenerateKeyedLoadWithNameKey(masm, key, receiver, x7, x3, x4, x5, x6, &slow);
622 
623  __ Bind(&index_name);
624  __ IndexFromHash(x3, key);
625  // Now jump to the place where smi keys are handled.
626  __ B(&index_smi);
627 }
628 
629 
630 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
631  // Return address is in lr.
632  Label miss;
633 
634  Register receiver = LoadDescriptor::ReceiverRegister();
635  Register index = LoadDescriptor::NameRegister();
636  Register result = x0;
637  Register scratch = x3;
638  DCHECK(!scratch.is(receiver) && !scratch.is(index));
639 
640  StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
641  &miss, // When not a string.
642  &miss, // When not a number.
643  &miss, // When index out of range.
645  char_at_generator.GenerateFast(masm);
646  __ Ret();
647 
648  StubRuntimeCallHelper call_helper;
649  char_at_generator.GenerateSlow(masm, call_helper);
650 
651  __ Bind(&miss);
652  GenerateMiss(masm);
653 }
654 
655 
656 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
657  ASM_LOCATION("KeyedStoreIC::GenerateMiss");
658 
659  // Push receiver, key and value for runtime call.
662 
663  ExternalReference ref =
664  ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate());
665  __ TailCallExternalReference(ref, 3, 1);
666 }
667 
668 
669 static void KeyedStoreGenerateGenericHelper(
670  MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
671  KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length,
672  Register value, Register key, Register receiver, Register receiver_map,
673  Register elements_map, Register elements) {
674  DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements,
675  x10, x11));
676 
677  Label transition_smi_elements;
678  Label transition_double_elements;
679  Label fast_double_without_map_check;
680  Label non_double_value;
681  Label finish_store;
682 
683  __ Bind(fast_object);
684  if (check_map == kCheckMap) {
685  __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
686  __ Cmp(elements_map,
687  Operand(masm->isolate()->factory()->fixed_array_map()));
688  __ B(ne, fast_double);
689  }
690 
691  // HOLECHECK: guards "A[i] = V"
692  // We have to go to the runtime if the current value is the hole because there
693  // may be a callback on the element.
694  Label holecheck_passed;
695  __ Add(x10, elements, FixedArray::kHeaderSize - kHeapObjectTag);
696  __ Add(x10, x10, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
697  __ Ldr(x11, MemOperand(x10));
698  __ JumpIfNotRoot(x11, Heap::kTheHoleValueRootIndex, &holecheck_passed);
699  __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, x10, slow);
700  __ bind(&holecheck_passed);
701 
702  // Smi stores don't require further checks.
703  __ JumpIfSmi(value, &finish_store);
704 
705  // Escape to elements kind transition case.
706  __ CheckFastObjectElements(receiver_map, x10, &transition_smi_elements);
707 
708  __ Bind(&finish_store);
709  if (increment_length == kIncrementLength) {
710  // Add 1 to receiver->length.
711  __ Add(x10, key, Smi::FromInt(1));
712  __ Str(x10, FieldMemOperand(receiver, JSArray::kLengthOffset));
713  }
714 
715  Register address = x11;
716  __ Add(address, elements, FixedArray::kHeaderSize - kHeapObjectTag);
717  __ Add(address, address, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
718  __ Str(value, MemOperand(address));
719 
720  Label dont_record_write;
721  __ JumpIfSmi(value, &dont_record_write);
722 
723  // Update write barrier for the elements array address.
724  __ Mov(x10, value); // Preserve the value which is returned.
725  __ RecordWrite(elements, address, x10, kLRHasNotBeenSaved, kDontSaveFPRegs,
727 
728  __ Bind(&dont_record_write);
729  __ Ret();
730 
731 
732  __ Bind(fast_double);
733  if (check_map == kCheckMap) {
734  // Check for fast double array case. If this fails, call through to the
735  // runtime.
736  __ JumpIfNotRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex, slow);
737  }
738 
739  // HOLECHECK: guards "A[i] double hole?"
740  // We have to see if the double version of the hole is present. If so go to
741  // the runtime.
742  __ Add(x10, elements, FixedDoubleArray::kHeaderSize - kHeapObjectTag);
743  __ Add(x10, x10, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
744  __ Ldr(x11, MemOperand(x10));
745  __ CompareAndBranch(x11, kHoleNanInt64, ne, &fast_double_without_map_check);
746  __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, x10, slow);
747 
748  __ Bind(&fast_double_without_map_check);
749  __ StoreNumberToDoubleElements(value, key, elements, x10, d0,
750  &transition_double_elements);
751  if (increment_length == kIncrementLength) {
752  // Add 1 to receiver->length.
753  __ Add(x10, key, Smi::FromInt(1));
754  __ Str(x10, FieldMemOperand(receiver, JSArray::kLengthOffset));
755  }
756  __ Ret();
757 
758 
759  __ Bind(&transition_smi_elements);
760  // Transition the array appropriately depending on the value type.
761  __ Ldr(x10, FieldMemOperand(value, HeapObject::kMapOffset));
762  __ JumpIfNotRoot(x10, Heap::kHeapNumberMapRootIndex, &non_double_value);
763 
764  // Value is a double. Transition FAST_SMI_ELEMENTS ->
765  // FAST_DOUBLE_ELEMENTS and complete the store.
766  __ LoadTransitionedArrayMapConditional(
767  FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, x10, x11, slow);
770  ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
771  receiver_map, mode, slow);
772  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
773  __ B(&fast_double_without_map_check);
774 
775  __ Bind(&non_double_value);
776  // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS.
777  __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS,
778  receiver_map, x10, x11, slow);
779 
782  masm, receiver, key, value, receiver_map, mode, slow);
783 
784  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
785  __ B(&finish_store);
786 
787  __ Bind(&transition_double_elements);
788  // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
789  // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
790  // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
791  __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
792  receiver_map, x10, x11, slow);
795  masm, receiver, key, value, receiver_map, mode, slow);
796  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
797  __ B(&finish_store);
798 }
799 
800 
801 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
802  StrictMode strict_mode) {
803  ASM_LOCATION("KeyedStoreIC::GenerateGeneric");
804  Label slow;
805  Label array;
806  Label fast_object;
807  Label extra;
808  Label fast_object_grow;
809  Label fast_double_grow;
810  Label fast_double;
811 
812  Register value = StoreDescriptor::ValueRegister();
813  Register key = StoreDescriptor::NameRegister();
814  Register receiver = StoreDescriptor::ReceiverRegister();
815  DCHECK(receiver.is(x1));
816  DCHECK(key.is(x2));
817  DCHECK(value.is(x0));
818 
819  Register receiver_map = x3;
820  Register elements = x4;
821  Register elements_map = x5;
822 
823  __ JumpIfNotSmi(key, &slow);
824  __ JumpIfSmi(receiver, &slow);
825  __ Ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset));
826 
827  // Check that the receiver does not require access checks and is not observed.
828  // The generic stub does not perform map checks or handle observed objects.
829  __ Ldrb(x10, FieldMemOperand(receiver_map, Map::kBitFieldOffset));
830  __ TestAndBranchIfAnySet(
831  x10, (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kIsObserved), &slow);
832 
833  // Check if the object is a JS array or not.
834  Register instance_type = x10;
835  __ CompareInstanceType(receiver_map, instance_type, JS_ARRAY_TYPE);
836  __ B(eq, &array);
837  // Check that the object is some kind of JSObject.
838  __ Cmp(instance_type, FIRST_JS_OBJECT_TYPE);
839  __ B(lt, &slow);
840 
841  // Object case: Check key against length in the elements array.
842  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
843  // Check array bounds. Both the key and the length of FixedArray are smis.
845  __ Cmp(x10, Operand::UntagSmi(key));
846  __ B(hi, &fast_object);
847 
848 
849  __ Bind(&slow);
850  // Slow case, handle jump to runtime.
851  // Live values:
852  // x0: value
853  // x1: key
854  // x2: receiver
856 
857 
858  __ Bind(&extra);
859  // Extra capacity case: Check if there is extra capacity to
860  // perform the store and update the length. Used for adding one
861  // element to the array by writing to array[array.length].
862 
863  // Check for room in the elements backing store.
864  // Both the key and the length of FixedArray are smis.
866  __ Cmp(x10, Operand::UntagSmi(key));
867  __ B(ls, &slow);
868 
869  __ Ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset));
870  __ Cmp(elements_map, Operand(masm->isolate()->factory()->fixed_array_map()));
871  __ B(eq, &fast_object_grow);
872  __ Cmp(elements_map,
873  Operand(masm->isolate()->factory()->fixed_double_array_map()));
874  __ B(eq, &fast_double_grow);
875  __ B(&slow);
876 
877 
878  __ Bind(&array);
879  // Array case: Get the length and the elements array from the JS
880  // array. Check that the array is in fast mode (and writable); if it
881  // is the length is always a smi.
882 
883  __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
884 
885  // Check the key against the length in the array.
886  __ Ldrsw(x10, UntagSmiFieldMemOperand(receiver, JSArray::kLengthOffset));
887  __ Cmp(x10, Operand::UntagSmi(key));
888  __ B(eq, &extra); // We can handle the case where we are appending 1 element.
889  __ B(lo, &slow);
890 
891  KeyedStoreGenerateGenericHelper(
892  masm, &fast_object, &fast_double, &slow, kCheckMap, kDontIncrementLength,
893  value, key, receiver, receiver_map, elements_map, elements);
894  KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
895  &slow, kDontCheckMap, kIncrementLength, value,
896  key, receiver, receiver_map, elements_map,
897  elements);
898 }
899 
900 
901 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
902  Register receiver = StoreDescriptor::ReceiverRegister();
903  Register name = StoreDescriptor::NameRegister();
905  x5, x6));
906 
907  // Probe the stub cache.
909  Code::ComputeHandlerFlags(Code::STORE_IC));
910  masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver,
911  name, x3, x4, x5, x6);
912 
913  // Cache miss: Jump to runtime.
914  GenerateMiss(masm);
915 }
916 
917 
918 void StoreIC::GenerateMiss(MacroAssembler* masm) {
921 
922  // Tail call to the entry.
923  ExternalReference ref =
924  ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate());
925  __ TailCallExternalReference(ref, 3, 1);
926 }
927 
928 
929 void StoreIC::GenerateNormal(MacroAssembler* masm) {
930  Label miss;
931  Register value = StoreDescriptor::ValueRegister();
932  Register receiver = StoreDescriptor::ReceiverRegister();
933  Register name = StoreDescriptor::NameRegister();
934  Register dictionary = x3;
935  DCHECK(!AreAliased(value, receiver, name, x3, x4, x5));
936 
937  __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
938 
939  GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5);
940  Counters* counters = masm->isolate()->counters();
941  __ IncrementCounter(counters->store_normal_hit(), 1, x4, x5);
942  __ Ret();
943 
944  // Cache miss: Jump to runtime.
945  __ Bind(&miss);
946  __ IncrementCounter(counters->store_normal_miss(), 1, x4, x5);
947  GenerateMiss(masm);
948 }
949 
950 
952  switch (op) {
953  case Token::EQ_STRICT:
954  case Token::EQ:
955  return eq;
956  case Token::LT:
957  return lt;
958  case Token::GT:
959  return gt;
960  case Token::LTE:
961  return le;
962  case Token::GTE:
963  return ge;
964  default:
965  UNREACHABLE();
966  return al;
967  }
968 }
969 
970 
972  // The address of the instruction following the call.
974 
975  InstructionSequence* patch_info = InstructionSequence::At(info_address);
976  return patch_info->IsInlineData();
977 }
978 
979 
980 // Activate a SMI fast-path by patching the instructions generated by
981 // JumpPatchSite::EmitJumpIf(Not)Smi(), using the information encoded by
982 // JumpPatchSite::EmitPatchInfo().
983 void PatchInlinedSmiCode(Address address, InlinedSmiCheck check) {
984  // The patch information is encoded in the instruction stream using
985  // instructions which have no side effects, so we can safely execute them.
986  // The patch information is encoded directly after the call to the helper
987  // function which is requesting this patch operation.
988  Address info_address = Assembler::return_address_from_call_start(address);
989  InlineSmiCheckInfo info(info_address);
990 
991  // Check and decode the patch information instruction.
992  if (!info.HasSmiCheck()) {
993  return;
994  }
995 
996  if (FLAG_trace_ic) {
997  PrintF("[ Patching ic at %p, marker=%p, SMI check=%p\n", address,
998  info_address, reinterpret_cast<void*>(info.SmiCheck()));
999  }
1000 
1001  // Patch and activate code generated by JumpPatchSite::EmitJumpIfNotSmi()
1002  // and JumpPatchSite::EmitJumpIfSmi().
1003  // Changing
1004  // tb(n)z xzr, #0, <target>
1005  // to
1006  // tb(!n)z test_reg, #0, <target>
1007  Instruction* to_patch = info.SmiCheck();
1008  PatchingAssembler patcher(to_patch, 1);
1009  DCHECK(to_patch->IsTestBranch());
1010  DCHECK(to_patch->ImmTestBranchBit5() == 0);
1011  DCHECK(to_patch->ImmTestBranchBit40() == 0);
1012 
1013  STATIC_ASSERT(kSmiTag == 0);
1014  STATIC_ASSERT(kSmiTagMask == 1);
1015 
1016  int branch_imm = to_patch->ImmTestBranch();
1017  Register smi_reg;
1018  if (check == ENABLE_INLINED_SMI_CHECK) {
1019  DCHECK(to_patch->Rt() == xzr.code());
1020  smi_reg = info.SmiRegister();
1021  } else {
1023  DCHECK(to_patch->Rt() != xzr.code());
1024  smi_reg = xzr;
1025  }
1026 
1027  if (to_patch->Mask(TestBranchMask) == TBZ) {
1028  // This is JumpIfNotSmi(smi_reg, branch_imm).
1029  patcher.tbnz(smi_reg, 0, branch_imm);
1030  } else {
1031  DCHECK(to_patch->Mask(TestBranchMask) == TBNZ);
1032  // This is JumpIfSmi(smi_reg, branch_imm).
1033  patcher.tbz(smi_reg, 0, branch_imm);
1034  }
1035 }
1036 }
1037 } // namespace v8::internal
1038 
1039 #endif // V8_TARGET_ARCH_ARM64
static AllocationSiteMode GetMode(ElementsKind boilerplate_elements_kind)
Definition: objects-inl.h:1591
static Address return_address_from_call_start(Address pc)
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
Isolate * isolate() const
Definition: ic.h:136
Address address() const
Definition: ic-inl.h:19
static InstructionSequence * At(Address address)
Counters * counters()
Definition: isolate.h:857
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 Operand UntagSmiAndScale(Register smi, int scale)
static Operand UntagSmi(Register smi)
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
#define ASM_LOCATION(message)
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
bool AreAliased(const CPURegister &reg1, const CPURegister &reg2, const CPURegister &reg3=NoReg, const CPURegister &reg4=NoReg, const CPURegister &reg5=NoReg, const CPURegister &reg6=NoReg, const CPURegister &reg7=NoReg, const CPURegister &reg8=NoReg)
const LowDwVfpRegister d0
InlinedSmiCheck
Definition: ic.h:672
@ DISABLE_INLINED_SMI_CHECK
Definition: ic.h:672
@ ENABLE_INLINED_SMI_CHECK
Definition: ic.h:672
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)
MemOperand FieldMemOperand(Register object, int offset)
byte * Address
Definition: globals.h:101
void PrintF(const char *format,...)
Definition: utils.cc:80
const int kHeapObjectTag
Definition: v8.h:5737
MemOperand UntagSmiFieldMemOperand(Register object, int offset)
const uint32_t kInternalizedTag
Definition: objects.h:551
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const uint64_t kHoleNanInt64
Definition: globals.h:660
const intptr_t kSmiTagMask
Definition: v8.h:5744
const uint32_t kIsNotInternalizedMask
Definition: objects.h:549
const int kSmiTag
Definition: v8.h:5742
KeyedStoreCheckMap
Definition: ic.h:524
@ kDontCheckMap
Definition: ic.h:524
@ kCheckMap
Definition: ic.h:524
@ STRING_INDEX_IS_ARRAY_INDEX
Definition: code-stubs.h:1595
const int64_t kXSignBit
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