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

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

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