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

Side by Side Diff: src/x64/ic-x64.cc

Issue 2255004: Cardmarking writebarrier. (Closed)
Patch Set: Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 Register key, 157 Register key,
158 Register r0, 158 Register r0,
159 Register r1, 159 Register r1,
160 Register r2) { 160 Register r2) {
161 // Register use: 161 // Register use:
162 // 162 //
163 // elements - holds the slow-case elements of the receiver and is unchanged. 163 // elements - holds the slow-case elements of the receiver and is unchanged.
164 // 164 //
165 // key - holds the smi key on entry and is unchanged if a branch is 165 // key - holds the smi key on entry and is unchanged if a branch is
166 // performed to the miss label. 166 // performed to the miss label.
167 // Holds the result on exit if the load succeeded.
167 // 168 //
168 // Scratch registers: 169 // Scratch registers:
169 // 170 //
170 // r0 - holds the untagged key on entry and holds the hash once computed. 171 // r0 - holds the untagged key on entry and holds the hash once computed.
171 // Holds the result on exit if the load succeeded.
172 // 172 //
173 // r1 - used to hold the capacity mask of the dictionary 173 // r1 - used to hold the capacity mask of the dictionary
174 // 174 //
175 // r2 - used for the index into the dictionary. 175 // r2 - used for the index into the dictionary.
176 Label done; 176 Label done;
177 177
178 // Compute the hash code from the untagged key. This must be kept in sync 178 // Compute the hash code from the untagged key. This must be kept in sync
179 // with ComputeIntegerHash in utils.h. 179 // with ComputeIntegerHash in utils.h.
180 // 180 //
181 // hash = ~hash + (hash << 15); 181 // hash = ~hash + (hash << 15);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 const int kDetailsOffset = 237 const int kDetailsOffset =
238 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 238 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
239 ASSERT_EQ(NORMAL, 0); 239 ASSERT_EQ(NORMAL, 0);
240 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 240 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
241 Smi::FromInt(PropertyDetails::TypeField::mask())); 241 Smi::FromInt(PropertyDetails::TypeField::mask()));
242 __ j(not_zero, miss); 242 __ j(not_zero, miss);
243 243
244 // Get the value at the masked, scaled index. 244 // Get the value at the masked, scaled index.
245 const int kValueOffset = 245 const int kValueOffset =
246 NumberDictionary::kElementsStartOffset + kPointerSize; 246 NumberDictionary::kElementsStartOffset + kPointerSize;
247 __ movq(r0, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 247 __ movq(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
248 } 248 }
249 249
250 250
251 // One byte opcode for test eax,0xXXXXXXXX. 251 // One byte opcode for test eax,0xXXXXXXXX.
252 static const byte kTestEaxByte = 0xA9; 252 static const byte kTestEaxByte = 0xA9;
253 253
254 254
255 static bool PatchInlinedMapCheck(Address address, Object* map) { 255 static bool PatchInlinedMapCheck(Address address, Object* map) {
256 // Arguments are address of start of call sequence that called 256 // Arguments are address of start of call sequence that called
257 // the IC, 257 // the IC,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 343 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
344 } 344 }
345 345
346 346
347 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 347 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
348 // ----------- S t a t e ------------- 348 // ----------- S t a t e -------------
349 // -- rsp[0] : return address 349 // -- rsp[0] : return address
350 // -- rsp[8] : name 350 // -- rsp[8] : name
351 // -- rsp[16] : receiver 351 // -- rsp[16] : receiver
352 // ----------------------------------- 352 // -----------------------------------
353 Label slow, check_string, index_int, index_string; 353 Label slow, check_string, index_smi, index_string;
354 Label check_pixel_array, probe_dictionary; 354 Label check_pixel_array, probe_dictionary;
355 Label check_number_dictionary; 355 Label check_number_dictionary;
356 356
357 // Load name and receiver. 357 // Load name and receiver.
358 __ movq(rax, Operand(rsp, kPointerSize)); 358 __ movq(rax, Operand(rsp, kPointerSize));
359 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); 359 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
360 360
361 // Check that the object isn't a smi. 361 // Check that the object isn't a smi.
362 __ JumpIfSmi(rcx, &slow); 362 __ JumpIfSmi(rcx, &slow);
363 363
364 // Check that the object is some kind of JS object EXCEPT JS Value type. 364 // Check that the object is some kind of JS object EXCEPT JS Value type.
365 // In the case that the object is a value-wrapper object, 365 // In the case that the object is a value-wrapper object,
366 // we enter the runtime system to make sure that indexing 366 // we enter the runtime system to make sure that indexing
367 // into string objects work as intended. 367 // into string objects work as intended.
368 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 368 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
369 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 369 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx);
370 __ j(below, &slow); 370 __ j(below, &slow);
371 371
372 // Check bit field. 372 // Check bit field.
373 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 373 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
374 Immediate(kSlowCaseBitFieldMask)); 374 Immediate(kSlowCaseBitFieldMask));
375 __ j(not_zero, &slow); 375 __ j(not_zero, &slow);
376 376
377 // Check that the key is a smi. 377 // Check that the key is a smi.
378 __ JumpIfNotSmi(rax, &check_string); 378 __ JumpIfNotSmi(rax, &check_string);
379 // Save key in rbx in case we want it for the number dictionary 379
380 // case.
381 __ movq(rbx, rax);
382 __ SmiToInteger32(rax, rax);
383 // Get the elements array of the object. 380 // Get the elements array of the object.
384 __ bind(&index_int); 381 __ bind(&index_smi);
385 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 382 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset));
386 // Check that the object is in fast mode (not dictionary). 383 // Check that the object is in fast mode (not dictionary).
387 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 384 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
388 Heap::kFixedArrayMapRootIndex); 385 Heap::kFixedArrayMapRootIndex);
389 __ j(not_equal, &check_pixel_array); 386 __ j(not_equal, &check_pixel_array);
390 // Check that the key (index) is within bounds. 387 // Check that the key (index) is within bounds.
391 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 388 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
392 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 389 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices.
393 // Fast case: Do the load. 390 // Fast case: Do the load.
394 __ movq(rax, Operand(rcx, rax, times_pointer_size, 391 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
395 FixedArray::kHeaderSize - kHeapObjectTag)); 392 __ movq(rax, FieldOperand(rcx,
393 index.reg,
394 index.scale,
395 FixedArray::kHeaderSize));
396 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 396 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
397 // In case the loaded value is the_hole we have to consult GetProperty 397 // In case the loaded value is the_hole we have to consult GetProperty
398 // to ensure the prototype chain is searched. 398 // to ensure the prototype chain is searched.
399 __ j(equal, &slow); 399 __ j(equal, &slow);
400 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 400 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
401 __ ret(0); 401 __ ret(0);
402 402
403 // Check whether the elements is a pixel array. 403 // Check whether the elements is a pixel array.
404 // rax: untagged index 404 // rax: key
405 // rcx: elements array 405 // rcx: elements array
406 __ bind(&check_pixel_array); 406 __ bind(&check_pixel_array);
407 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 407 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
408 Heap::kPixelArrayMapRootIndex); 408 Heap::kPixelArrayMapRootIndex);
409 __ j(not_equal, &check_number_dictionary); 409 __ j(not_equal, &check_number_dictionary);
410 __ SmiToInteger32(rax, rax);
410 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); 411 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
411 __ j(above_equal, &slow); 412 __ j(above_equal, &slow);
412 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 413 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
413 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 414 __ movzxbq(rax, Operand(rcx, rax, times_1, 0));
414 __ Integer32ToSmi(rax, rax); 415 __ Integer32ToSmi(rax, rax);
415 __ ret(0); 416 __ ret(0);
416 417
417 __ bind(&check_number_dictionary); 418 __ bind(&check_number_dictionary);
418 // Check whether the elements is a number dictionary. 419 // Check whether the elements is a number dictionary.
419 // rax: untagged index 420 // rax: key
420 // rbx: key
421 // rcx: elements 421 // rcx: elements
422 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 422 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
423 Heap::kHashTableMapRootIndex); 423 Heap::kHashTableMapRootIndex);
424 __ j(not_equal, &slow); 424 __ j(not_equal, &slow);
425 GenerateNumberDictionaryLoad(masm, &slow, rcx, rbx, rax, rdx, rdi); 425 __ SmiToInteger32(rbx, rax);
426 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, rdx, rdi);
426 __ ret(0); 427 __ ret(0);
427 428
428 // Slow case: Load name and receiver from stack and jump to runtime. 429 // Slow case: Load name and receiver from stack and jump to runtime.
429 __ bind(&slow); 430 __ bind(&slow);
430 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 431 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
431 GenerateRuntimeGetProperty(masm); 432 GenerateRuntimeGetProperty(masm);
432 __ bind(&check_string); 433 __ bind(&check_string);
433 // The key is not a smi. 434 // The key is not a smi.
434 // Is it a string? 435 // Is it a string?
435 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 436 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 __ movq(rax, rcx); 505 __ movq(rax, rcx);
505 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 506 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
506 __ ret(0); 507 __ ret(0);
507 // If the hash field contains an array index pick it out. The assert checks 508 // If the hash field contains an array index pick it out. The assert checks
508 // that the constants for the maximum number of digits for an array index 509 // that the constants for the maximum number of digits for an array index
509 // cached in the hash field and the number of bits reserved for it does not 510 // cached in the hash field and the number of bits reserved for it does not
510 // conflict. 511 // conflict.
511 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 512 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
512 (1 << String::kArrayIndexValueBits)); 513 (1 << String::kArrayIndexValueBits));
513 __ bind(&index_string); 514 __ bind(&index_string);
514 __ movl(rax, rbx); 515 // We want the smi-tagged index in rax.
515 __ and_(rax, Immediate(String::kArrayIndexHashMask)); 516 __ and_(rbx, Immediate(String::kArrayIndexValueMask));
516 __ shrl(rax, Immediate(String::kHashShift)); 517 __ shr(rbx, Immediate(String::kHashShift));
517 __ jmp(&index_int); 518 __ Integer32ToSmi(rax, rbx);
519 __ jmp(&index_smi);
518 } 520 }
519 521
520 522
521 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 523 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
522 // ----------- S t a t e ------------- 524 // ----------- S t a t e -------------
523 // -- rsp[0] : return address 525 // -- rsp[0] : return address
524 // -- rsp[8] : name (index) 526 // -- rsp[8] : name (index)
525 // -- rsp[16] : receiver 527 // -- rsp[16] : receiver
526 // ----------------------------------- 528 // -----------------------------------
527 Label miss; 529 Label miss;
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 813
812 // Object case: Check key against length in the elements array. 814 // Object case: Check key against length in the elements array.
813 // rax: value 815 // rax: value
814 // rdx: JSObject 816 // rdx: JSObject
815 // rcx: index (as a smi) 817 // rcx: index (as a smi)
816 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 818 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
817 // Check that the object is in fast mode (not dictionary). 819 // Check that the object is in fast mode (not dictionary).
818 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 820 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
819 Heap::kFixedArrayMapRootIndex); 821 Heap::kFixedArrayMapRootIndex);
820 __ j(not_equal, &check_pixel_array); 822 __ j(not_equal, &check_pixel_array);
821 // Untag the key (for checking against untagged length in the fixed array). 823 __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
822 __ SmiToInteger32(rdi, rcx);
823 __ cmpl(rdi, FieldOperand(rbx, Array::kLengthOffset));
824 // rax: value 824 // rax: value
825 // rbx: FixedArray 825 // rbx: FixedArray
826 // rcx: index (as a smi) 826 // rcx: index (as a smi)
827 __ j(below, &fast); 827 __ j(below, &fast);
828 828
829 // Slow case: call runtime. 829 // Slow case: call runtime.
830 __ bind(&slow); 830 __ bind(&slow);
831 GenerateRuntimeSetProperty(masm); 831 GenerateRuntimeSetProperty(masm);
832 832
833 // Check whether the elements is a pixel array. 833 // Check whether the elements is a pixel array.
(...skipping 28 matching lines...) Expand all
862 // Extra capacity case: Check if there is extra capacity to 862 // Extra capacity case: Check if there is extra capacity to
863 // perform the store and update the length. Used for adding one 863 // perform the store and update the length. Used for adding one
864 // element to the array by writing to array[array.length]. 864 // element to the array by writing to array[array.length].
865 __ bind(&extra); 865 __ bind(&extra);
866 // rax: value 866 // rax: value
867 // rdx: receiver (a JSArray) 867 // rdx: receiver (a JSArray)
868 // rbx: receiver's elements array (a FixedArray) 868 // rbx: receiver's elements array (a FixedArray)
869 // rcx: index (as a smi) 869 // rcx: index (as a smi)
870 // flags: smicompare (rdx.length(), rbx) 870 // flags: smicompare (rdx.length(), rbx)
871 __ j(not_equal, &slow); // do not leave holes in the array 871 __ j(not_equal, &slow); // do not leave holes in the array
872 __ SmiToInteger64(rdi, rcx); 872 __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
873 __ cmpl(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
874 __ j(above_equal, &slow); 873 __ j(above_equal, &slow);
875 // Increment and restore smi-tag. 874 // Increment index to get new length.
876 __ Integer64PlusConstantToSmi(rdi, rdi, 1); 875 __ SmiAddConstant(rdi, rcx, Smi::FromInt(1));
877 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi); 876 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
878 __ jmp(&fast); 877 __ jmp(&fast);
879 878
880 // Array case: Get the length and the elements array from the JS 879 // Array case: Get the length and the elements array from the JS
881 // array. Check that the array is in fast mode; if it is the 880 // array. Check that the array is in fast mode; if it is the
882 // length is always a smi. 881 // length is always a smi.
883 __ bind(&array); 882 __ bind(&array);
884 // rax: value 883 // rax: value
885 // rdx: receiver (a JSArray) 884 // rdx: receiver (a JSArray)
886 // rcx: index (as a smi) 885 // rcx: index (as a smi)
887 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 886 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
888 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 887 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
889 Heap::kFixedArrayMapRootIndex); 888 Heap::kFixedArrayMapRootIndex);
890 __ j(not_equal, &slow); 889 __ j(not_equal, &slow);
891 890
892 // Check the key against the length in the array, compute the 891 // Check the key against the length in the array, compute the
893 // address to store into and fall through to fast case. 892 // address to store into and fall through to fast case.
894 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx); 893 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
895 __ j(below_equal, &extra); 894 __ j(below_equal, &extra);
896 895
897 // Fast case: Do the store. 896 // Fast case: Do the store.
898 __ bind(&fast); 897 __ bind(&fast);
899 // rax: value 898 // rax: value
900 // rbx: receiver's elements array (a FixedArray) 899 // rbx: receiver's elements array (a FixedArray)
901 // rcx: index (as a smi) 900 // rcx: index (as a smi)
902 Label non_smi_value; 901 Label non_smi_value;
903 __ JumpIfNotSmi(rax, &non_smi_value); 902 __ JumpIfNotSmi(rax, &non_smi_value);
904 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2); 903 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
905 __ movq(Operand(rbx, index.reg, index.scale, 904 __ movq(FieldOperand(rbx, index.reg, index.scale, FixedArray::kHeaderSize),
906 FixedArray::kHeaderSize - kHeapObjectTag),
907 rax); 905 rax);
908 __ ret(0); 906 __ ret(0);
909 __ bind(&non_smi_value); 907 __ bind(&non_smi_value);
910 // Slow case that needs to retain rcx for use by RecordWrite. 908 // Slow case that needs to retain rcx for use by RecordWrite.
911 // Update write barrier for the elements array address. 909 // Update write barrier for the elements array address.
912 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2); 910 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2);
913 __ movq(Operand(rbx, index2.reg, index2.scale, 911 __ movq(FieldOperand(rbx, index2.reg, index2.scale, FixedArray::kHeaderSize),
914 FixedArray::kHeaderSize - kHeapObjectTag),
915 rax); 912 rax);
916 __ movq(rdx, rax); 913 __ movq(rdx, rax);
917 __ RecordWriteNonSmi(rbx, 0, rdx, rcx); 914 __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
918 __ ret(0); 915 __ ret(0);
919 } 916 }
920 917
921 918
922 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 919 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
923 ExternalArrayType array_type) { 920 ExternalArrayType array_type) {
924 // ----------- S t a t e ------------- 921 // ----------- S t a t e -------------
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 GenerateMiss(masm); 1579 GenerateMiss(masm);
1583 } 1580 }
1584 1581
1585 1582
1586 #undef __ 1583 #undef __
1587 1584
1588 1585
1589 } } // namespace v8::internal 1586 } } // namespace v8::internal
1590 1587
1591 #endif // V8_TARGET_ARCH_X64 1588 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/full-codegen-x64.cc ('k') | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698