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

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

Issue 2114015: Cardmarking writebarrier. (Closed)
Patch Set: Created 10 years, 7 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
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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 Register key, 158 Register key,
159 Register r0, 159 Register r0,
160 Register r1, 160 Register r1,
161 Register r2) { 161 Register r2) {
162 // Register use: 162 // Register use:
163 // 163 //
164 // elements - holds the slow-case elements of the receiver and is unchanged. 164 // elements - holds the slow-case elements of the receiver and is unchanged.
165 // 165 //
166 // key - holds the smi key on entry and is unchanged if a branch is 166 // key - holds the smi key on entry and is unchanged if a branch is
167 // performed to the miss label. 167 // performed to the miss label.
168 // Holds the result on exit if the load succeeded.
168 // 169 //
169 // Scratch registers: 170 // Scratch registers:
170 // 171 //
171 // r0 - holds the untagged key on entry and holds the hash once computed. 172 // r0 - holds the untagged key on entry and holds the hash once computed.
172 // Holds the result on exit if the load succeeded.
173 // 173 //
174 // r1 - used to hold the capacity mask of the dictionary 174 // r1 - used to hold the capacity mask of the dictionary
175 // 175 //
176 // r2 - used for the index into the dictionary. 176 // r2 - used for the index into the dictionary.
177 Label done; 177 Label done;
178 178
179 // Compute the hash code from the untagged key. This must be kept in sync 179 // Compute the hash code from the untagged key. This must be kept in sync
180 // with ComputeIntegerHash in utils.h. 180 // with ComputeIntegerHash in utils.h.
181 // 181 //
182 // hash = ~hash + (hash << 15); 182 // hash = ~hash + (hash << 15);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 const int kDetailsOffset = 238 const int kDetailsOffset =
239 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; 239 NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
240 ASSERT_EQ(NORMAL, 0); 240 ASSERT_EQ(NORMAL, 0);
241 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), 241 __ Test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset),
242 Smi::FromInt(PropertyDetails::TypeField::mask())); 242 Smi::FromInt(PropertyDetails::TypeField::mask()));
243 __ j(not_zero, miss); 243 __ j(not_zero, miss);
244 244
245 // Get the value at the masked, scaled index. 245 // Get the value at the masked, scaled index.
246 const int kValueOffset = 246 const int kValueOffset =
247 NumberDictionary::kElementsStartOffset + kPointerSize; 247 NumberDictionary::kElementsStartOffset + kPointerSize;
248 __ movq(r0, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); 248 __ movq(key, FieldOperand(elements, r2, times_pointer_size, kValueOffset));
249 } 249 }
250 250
251 251
252 // One byte opcode for test eax,0xXXXXXXXX. 252 // One byte opcode for test eax,0xXXXXXXXX.
253 static const byte kTestEaxByte = 0xA9; 253 static const byte kTestEaxByte = 0xA9;
254 254
255 255
256 static bool PatchInlinedMapCheck(Address address, Object* map) { 256 static bool PatchInlinedMapCheck(Address address, Object* map) {
257 // Arguments are address of start of call sequence that called 257 // Arguments are address of start of call sequence that called
258 // the IC, 258 // the IC,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 344 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
345 } 345 }
346 346
347 347
348 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 348 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
349 // ----------- S t a t e ------------- 349 // ----------- S t a t e -------------
350 // -- rsp[0] : return address 350 // -- rsp[0] : return address
351 // -- rsp[8] : name 351 // -- rsp[8] : name
352 // -- rsp[16] : receiver 352 // -- rsp[16] : receiver
353 // ----------------------------------- 353 // -----------------------------------
354 Label slow, check_string, index_int, index_string; 354 Label slow, check_string, index_smi, index_string;
355 Label check_pixel_array, probe_dictionary; 355 Label check_pixel_array, probe_dictionary;
356 Label check_number_dictionary; 356 Label check_number_dictionary;
357 357
358 // Load name and receiver. 358 // Load name and receiver.
359 __ movq(rax, Operand(rsp, kPointerSize)); 359 __ movq(rax, Operand(rsp, kPointerSize));
360 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); 360 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
361 361
362 // Check that the object isn't a smi. 362 // Check that the object isn't a smi.
363 __ JumpIfSmi(rcx, &slow); 363 __ JumpIfSmi(rcx, &slow);
364 364
365 // Check that the object is some kind of JS object EXCEPT JS Value type. 365 // Check that the object is some kind of JS object EXCEPT JS Value type.
366 // In the case that the object is a value-wrapper object, 366 // In the case that the object is a value-wrapper object,
367 // we enter the runtime system to make sure that indexing 367 // we enter the runtime system to make sure that indexing
368 // into string objects work as intended. 368 // into string objects work as intended.
369 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); 369 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE);
370 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); 370 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx);
371 __ j(below, &slow); 371 __ j(below, &slow);
372 372
373 // Check bit field. 373 // Check bit field.
374 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 374 __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
375 Immediate(kSlowCaseBitFieldMask)); 375 Immediate(kSlowCaseBitFieldMask));
376 __ j(not_zero, &slow); 376 __ j(not_zero, &slow);
377 377
378 // Check that the key is a smi. 378 // Check that the key is a smi.
379 __ JumpIfNotSmi(rax, &check_string); 379 __ JumpIfNotSmi(rax, &check_string);
380 // Save key in rbx in case we want it for the number dictionary 380
381 // case.
382 __ movq(rbx, rax);
383 __ SmiToInteger32(rax, rax);
384 // Get the elements array of the object. 381 // Get the elements array of the object.
385 __ bind(&index_int); 382 __ bind(&index_smi);
386 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); 383 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset));
387 // Check that the object is in fast mode (not dictionary). 384 // Check that the object is in fast mode (not dictionary).
388 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 385 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
389 Heap::kFixedArrayMapRootIndex); 386 Heap::kFixedArrayMapRootIndex);
390 __ j(not_equal, &check_pixel_array); 387 __ j(not_equal, &check_pixel_array);
391 // Check that the key (index) is within bounds. 388 // Check that the key (index) is within bounds.
392 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 389 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
393 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices. 390 __ j(above_equal, &slow); // Unsigned comparison rejects negative indices.
394 // Fast case: Do the load. 391 // Fast case: Do the load.
395 __ movq(rax, Operand(rcx, rax, times_pointer_size, 392 SmiIndex index = masm->SmiToIndex(rax, rax, kPointerSizeLog2);
396 FixedArray::kHeaderSize - kHeapObjectTag)); 393 __ movq(rax, FieldOperand(rcx,
394 index.reg,
395 index.scale,
396 FixedArray::kHeaderSize));
397 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 397 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
398 // In case the loaded value is the_hole we have to consult GetProperty 398 // In case the loaded value is the_hole we have to consult GetProperty
399 // to ensure the prototype chain is searched. 399 // to ensure the prototype chain is searched.
400 __ j(equal, &slow); 400 __ j(equal, &slow);
401 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); 401 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1);
402 __ ret(0); 402 __ ret(0);
403 403
404 // Check whether the elements is a pixel array. 404 // Check whether the elements is a pixel array.
405 // rax: untagged index 405 // rax: key
406 // rcx: elements array 406 // rcx: elements array
407 __ bind(&check_pixel_array); 407 __ bind(&check_pixel_array);
408 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 408 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
409 Heap::kPixelArrayMapRootIndex); 409 Heap::kPixelArrayMapRootIndex);
410 __ j(not_equal, &check_number_dictionary); 410 __ j(not_equal, &check_number_dictionary);
411 __ SmiToInteger32(rax, rax);
411 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset)); 412 __ cmpl(rax, FieldOperand(rcx, PixelArray::kLengthOffset));
412 __ j(above_equal, &slow); 413 __ j(above_equal, &slow);
413 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset)); 414 __ movq(rcx, FieldOperand(rcx, PixelArray::kExternalPointerOffset));
414 __ movzxbq(rax, Operand(rcx, rax, times_1, 0)); 415 __ movzxbq(rax, Operand(rcx, rax, times_1, 0));
415 __ Integer32ToSmi(rax, rax); 416 __ Integer32ToSmi(rax, rax);
416 __ ret(0); 417 __ ret(0);
417 418
418 __ bind(&check_number_dictionary); 419 __ bind(&check_number_dictionary);
419 // Check whether the elements is a number dictionary. 420 // Check whether the elements is a number dictionary.
420 // rax: untagged index 421 // rax: key
421 // rbx: key
422 // rcx: elements 422 // rcx: elements
423 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), 423 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset),
424 Heap::kHashTableMapRootIndex); 424 Heap::kHashTableMapRootIndex);
425 __ j(not_equal, &slow); 425 __ j(not_equal, &slow);
426 GenerateNumberDictionaryLoad(masm, &slow, rcx, rbx, rax, rdx, rdi); 426 __ SmiToInteger32(rbx, rax);
427 GenerateNumberDictionaryLoad(masm, &slow, rcx, rax, rbx, rdx, rdi);
427 __ ret(0); 428 __ ret(0);
428 429
429 // Slow case: Load name and receiver from stack and jump to runtime. 430 // Slow case: Load name and receiver from stack and jump to runtime.
430 __ bind(&slow); 431 __ bind(&slow);
431 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1); 432 __ IncrementCounter(&Counters::keyed_load_generic_slow, 1);
432 GenerateRuntimeGetProperty(masm); 433 GenerateRuntimeGetProperty(masm);
433 __ bind(&check_string); 434 __ bind(&check_string);
434 // The key is not a smi. 435 // The key is not a smi.
435 // Is it a string? 436 // Is it a string?
436 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 437 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 __ movq(rax, rcx); 506 __ movq(rax, rcx);
506 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); 507 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
507 __ ret(0); 508 __ ret(0);
508 // If the hash field contains an array index pick it out. The assert checks 509 // If the hash field contains an array index pick it out. The assert checks
509 // that the constants for the maximum number of digits for an array index 510 // that the constants for the maximum number of digits for an array index
510 // cached in the hash field and the number of bits reserved for it does not 511 // cached in the hash field and the number of bits reserved for it does not
511 // conflict. 512 // conflict.
512 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < 513 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
513 (1 << String::kArrayIndexValueBits)); 514 (1 << String::kArrayIndexValueBits));
514 __ bind(&index_string); 515 __ bind(&index_string);
515 __ movl(rax, rbx); 516 // We want the smi-tagged index in rax.
516 __ and_(rax, Immediate(String::kArrayIndexHashMask)); 517 __ and_(rbx, Immediate(String::kArrayIndexValueMask));
517 __ shrl(rax, Immediate(String::kHashShift)); 518 __ shr(rbx, Immediate(String::kHashShift));
518 __ jmp(&index_int); 519 __ Integer32ToSmi(rax, rbx);
520 __ jmp(&index_smi);
519 } 521 }
520 522
521 523
522 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 524 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
523 // ----------- S t a t e ------------- 525 // ----------- S t a t e -------------
524 // -- rsp[0] : return address 526 // -- rsp[0] : return address
525 // -- rsp[8] : name 527 // -- rsp[8] : name
526 // -- rsp[16] : receiver 528 // -- rsp[16] : receiver
527 // ----------------------------------- 529 // -----------------------------------
528 Label miss; 530 Label miss;
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 847
846 // Object case: Check key against length in the elements array. 848 // Object case: Check key against length in the elements array.
847 // rax: value 849 // rax: value
848 // rdx: JSObject 850 // rdx: JSObject
849 // rcx: index (as a smi) 851 // rcx: index (as a smi)
850 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 852 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
851 // Check that the object is in fast mode (not dictionary). 853 // Check that the object is in fast mode (not dictionary).
852 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 854 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
853 Heap::kFixedArrayMapRootIndex); 855 Heap::kFixedArrayMapRootIndex);
854 __ j(not_equal, &check_pixel_array); 856 __ j(not_equal, &check_pixel_array);
855 // Untag the key (for checking against untagged length in the fixed array). 857 __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
856 __ SmiToInteger32(rdi, rcx);
857 __ cmpl(rdi, FieldOperand(rbx, Array::kLengthOffset));
858 // rax: value 858 // rax: value
859 // rbx: FixedArray 859 // rbx: FixedArray
860 // rcx: index (as a smi) 860 // rcx: index (as a smi)
861 __ j(below, &fast); 861 __ j(below, &fast);
862 862
863 // Slow case: call runtime. 863 // Slow case: call runtime.
864 __ bind(&slow); 864 __ bind(&slow);
865 GenerateRuntimeSetProperty(masm); 865 GenerateRuntimeSetProperty(masm);
866 866
867 // Check whether the elements is a pixel array. 867 // Check whether the elements is a pixel array.
(...skipping 28 matching lines...) Expand all
896 // Extra capacity case: Check if there is extra capacity to 896 // Extra capacity case: Check if there is extra capacity to
897 // perform the store and update the length. Used for adding one 897 // perform the store and update the length. Used for adding one
898 // element to the array by writing to array[array.length]. 898 // element to the array by writing to array[array.length].
899 __ bind(&extra); 899 __ bind(&extra);
900 // rax: value 900 // rax: value
901 // rdx: receiver (a JSArray) 901 // rdx: receiver (a JSArray)
902 // rbx: receiver's elements array (a FixedArray) 902 // rbx: receiver's elements array (a FixedArray)
903 // rcx: index (as a smi) 903 // rcx: index (as a smi)
904 // flags: smicompare (rdx.length(), rbx) 904 // flags: smicompare (rdx.length(), rbx)
905 __ j(not_equal, &slow); // do not leave holes in the array 905 __ j(not_equal, &slow); // do not leave holes in the array
906 __ SmiToInteger64(rdi, rcx); 906 __ SmiCompare(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
907 __ cmpl(rdi, FieldOperand(rbx, FixedArray::kLengthOffset));
908 __ j(above_equal, &slow); 907 __ j(above_equal, &slow);
909 // Increment and restore smi-tag. 908 // Increment index to get new length.
910 __ Integer64PlusConstantToSmi(rdi, rdi, 1); 909 __ SmiAddConstant(rdi, rcx, Smi::FromInt(1));
911 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi); 910 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rdi);
912 __ jmp(&fast); 911 __ jmp(&fast);
913 912
914 // Array case: Get the length and the elements array from the JS 913 // Array case: Get the length and the elements array from the JS
915 // array. Check that the array is in fast mode; if it is the 914 // array. Check that the array is in fast mode; if it is the
916 // length is always a smi. 915 // length is always a smi.
917 __ bind(&array); 916 __ bind(&array);
918 // rax: value 917 // rax: value
919 // rdx: receiver (a JSArray) 918 // rdx: receiver (a JSArray)
920 // rcx: index (as a smi) 919 // rcx: index (as a smi)
921 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 920 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
922 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 921 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
923 Heap::kFixedArrayMapRootIndex); 922 Heap::kFixedArrayMapRootIndex);
924 __ j(not_equal, &slow); 923 __ j(not_equal, &slow);
925 924
926 // Check the key against the length in the array, compute the 925 // Check the key against the length in the array, compute the
927 // address to store into and fall through to fast case. 926 // address to store into and fall through to fast case.
928 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx); 927 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rcx);
929 __ j(below_equal, &extra); 928 __ j(below_equal, &extra);
930 929
931 // Fast case: Do the store. 930 // Fast case: Do the store.
932 __ bind(&fast); 931 __ bind(&fast);
933 // rax: value 932 // rax: value
934 // rbx: receiver's elements array (a FixedArray) 933 // rbx: receiver's elements array (a FixedArray)
935 // rcx: index (as a smi) 934 // rcx: index (as a smi)
936 Label non_smi_value; 935 Label non_smi_value;
937 __ JumpIfNotSmi(rax, &non_smi_value); 936 __ JumpIfNotSmi(rax, &non_smi_value);
938 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2); 937 SmiIndex index = masm->SmiToIndex(rcx, rcx, kPointerSizeLog2);
939 __ movq(Operand(rbx, index.reg, index.scale, 938 __ movq(FieldOperand(rbx, index.reg, index.scale, FixedArray::kHeaderSize),
940 FixedArray::kHeaderSize - kHeapObjectTag),
941 rax); 939 rax);
942 __ ret(0); 940 __ ret(0);
943 __ bind(&non_smi_value); 941 __ bind(&non_smi_value);
944 // Slow case that needs to retain rcx for use by RecordWrite. 942 // Slow case that needs to retain rcx for use by RecordWrite.
945 // Update write barrier for the elements array address. 943 // Update write barrier for the elements array address.
946 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2); 944 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rcx, kPointerSizeLog2);
947 __ movq(Operand(rbx, index2.reg, index2.scale, 945 __ movq(FieldOperand(rbx, index2.reg, index2.scale, FixedArray::kHeaderSize),
948 FixedArray::kHeaderSize - kHeapObjectTag),
949 rax); 946 rax);
950 __ movq(rdx, rax); 947 __ movq(rdx, rax);
951 __ RecordWriteNonSmi(rbx, 0, rdx, rcx); 948 __ RecordWriteNonSmi(rbx, 0, rdx, rcx);
952 __ ret(0); 949 __ ret(0);
953 } 950 }
954 951
955 952
956 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm, 953 void KeyedStoreIC::GenerateExternalArray(MacroAssembler* masm,
957 ExternalArrayType array_type) { 954 ExternalArrayType array_type) {
958 // ----------- S t a t e ------------- 955 // ----------- S t a t e -------------
(...skipping 657 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 GenerateMiss(masm); 1613 GenerateMiss(masm);
1617 } 1614 }
1618 1615
1619 1616
1620 #undef __ 1617 #undef __
1621 1618
1622 1619
1623 } } // namespace v8::internal 1620 } } // namespace v8::internal
1624 1621
1625 #endif // V8_TARGET_ARCH_X64 1622 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698