OLD | NEW |
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 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 // we enter the runtime system to make sure that indexing | 445 // we enter the runtime system to make sure that indexing |
446 // into string objects works as intended. | 446 // into string objects works as intended. |
447 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 447 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
448 | 448 |
449 __ CmpInstanceType(map, JS_OBJECT_TYPE); | 449 __ CmpInstanceType(map, JS_OBJECT_TYPE); |
450 __ j(below, slow, not_taken); | 450 __ j(below, slow, not_taken); |
451 } | 451 } |
452 | 452 |
453 | 453 |
454 // Loads an indexed element from a fast case array. | 454 // Loads an indexed element from a fast case array. |
| 455 // If not_fast_array is NULL, doesn't perform the elements map check. |
455 static void GenerateFastArrayLoad(MacroAssembler* masm, | 456 static void GenerateFastArrayLoad(MacroAssembler* masm, |
456 Register receiver, | 457 Register receiver, |
457 Register key, | 458 Register key, |
458 Register scratch, | 459 Register scratch, |
459 Register result, | 460 Register result, |
460 Label* not_fast_array, | 461 Label* not_fast_array, |
461 Label* out_of_range) { | 462 Label* out_of_range) { |
462 // Register use: | 463 // Register use: |
463 // receiver - holds the receiver and is unchanged. | 464 // receiver - holds the receiver and is unchanged. |
464 // key - holds the key and is unchanged (must be a smi). | 465 // key - holds the key and is unchanged (must be a smi). |
465 // Scratch registers: | 466 // Scratch registers: |
466 // scratch - used to hold elements of the receiver and the loaded value. | 467 // scratch - used to hold elements of the receiver and the loaded value. |
467 // result - holds the result on exit if the load succeeds and | 468 // result - holds the result on exit if the load succeeds and |
468 // we fall through. | 469 // we fall through. |
469 | 470 |
470 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); | 471 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); |
471 // Check that the object is in fast mode (not dictionary). | 472 if (not_fast_array != NULL) { |
472 __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); | 473 // Check that the object is in fast mode and writable. |
| 474 __ CheckMap(scratch, Factory::fixed_array_map(), not_fast_array, true); |
| 475 } else { |
| 476 __ AssertFastElements(scratch); |
| 477 } |
473 // Check that the key (index) is within bounds. | 478 // Check that the key (index) is within bounds. |
474 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); | 479 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); |
475 __ j(above_equal, out_of_range); | 480 __ j(above_equal, out_of_range); |
476 // Fast case: Do the load. | 481 // Fast case: Do the load. |
477 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); | 482 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
478 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); | 483 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); |
479 __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); | 484 __ cmp(Operand(scratch), Immediate(Factory::the_hole_value())); |
480 // In case the loaded value is the_hole we have to consult GetProperty | 485 // In case the loaded value is the_hole we have to consult GetProperty |
481 // to ensure the prototype chain is searched. | 486 // to ensure the prototype chain is searched. |
482 __ j(equal, out_of_range); | 487 __ j(equal, out_of_range); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 // Check that the key is a smi. | 556 // Check that the key is a smi. |
552 __ test(eax, Immediate(kSmiTagMask)); | 557 __ test(eax, Immediate(kSmiTagMask)); |
553 __ j(not_zero, &check_string, not_taken); | 558 __ j(not_zero, &check_string, not_taken); |
554 __ bind(&index_smi); | 559 __ bind(&index_smi); |
555 // Now the key is known to be a smi. This place is also jumped to from | 560 // Now the key is known to be a smi. This place is also jumped to from |
556 // where a numeric string is converted to a smi. | 561 // where a numeric string is converted to a smi. |
557 | 562 |
558 GenerateKeyedLoadReceiverCheck( | 563 GenerateKeyedLoadReceiverCheck( |
559 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); | 564 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); |
560 | 565 |
| 566 // Check the "has fast elements" bit in the receiver's map which is |
| 567 // now in ecx. |
| 568 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), |
| 569 1 << Map::kHasFastElements); |
| 570 __ j(zero, &check_pixel_array, not_taken); |
| 571 |
561 GenerateFastArrayLoad(masm, | 572 GenerateFastArrayLoad(masm, |
562 edx, | 573 edx, |
563 eax, | 574 eax, |
564 ecx, | 575 ecx, |
565 eax, | 576 eax, |
566 &check_pixel_array, | 577 NULL, |
567 &slow); | 578 &slow); |
568 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 579 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
569 __ ret(0); | 580 __ ret(0); |
570 | 581 |
571 __ bind(&check_pixel_array); | 582 __ bind(&check_pixel_array); |
572 // Check whether the elements is a pixel array. | 583 // Check whether the elements is a pixel array. |
573 // edx: receiver | 584 // edx: receiver |
574 // eax: key | 585 // eax: key |
575 // ecx: elements | 586 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
576 __ mov(ebx, eax); | 587 __ mov(ebx, eax); |
577 __ SmiUntag(ebx); | 588 __ SmiUntag(ebx); |
578 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); | 589 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); |
579 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 590 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
580 __ j(above_equal, &slow); | 591 __ j(above_equal, &slow); |
581 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 592 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
582 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); | 593 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); |
583 __ SmiTag(eax); | 594 __ SmiTag(eax); |
584 __ ret(0); | 595 __ ret(0); |
585 | 596 |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 __ j(equal, &array); | 971 __ j(equal, &array); |
961 // Check that the object is some kind of JS object. | 972 // Check that the object is some kind of JS object. |
962 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 973 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
963 __ j(below, &slow, not_taken); | 974 __ j(below, &slow, not_taken); |
964 | 975 |
965 // Object case: Check key against length in the elements array. | 976 // Object case: Check key against length in the elements array. |
966 // eax: value | 977 // eax: value |
967 // edx: JSObject | 978 // edx: JSObject |
968 // ecx: key (a smi) | 979 // ecx: key (a smi) |
969 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 980 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
970 // Check that the object is in fast mode (not dictionary). | 981 // Check that the object is in fast mode and writable. |
971 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 982 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
972 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 983 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
973 __ j(below, &fast, taken); | 984 __ j(below, &fast, taken); |
974 | 985 |
975 // Slow case: call runtime. | 986 // Slow case: call runtime. |
976 __ bind(&slow); | 987 __ bind(&slow); |
977 GenerateRuntimeSetProperty(masm); | 988 GenerateRuntimeSetProperty(masm); |
978 | 989 |
979 // Check whether the elements is a pixel array. | 990 // Check whether the elements is a pixel array. |
980 __ bind(&check_pixel_array); | 991 __ bind(&check_pixel_array); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 // flags: compare (ecx, edx.length()) | 1027 // flags: compare (ecx, edx.length()) |
1017 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 1028 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
1018 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 1029 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
1019 __ j(above_equal, &slow, not_taken); | 1030 __ j(above_equal, &slow, not_taken); |
1020 // Add 1 to receiver->length, and go to fast array write. | 1031 // Add 1 to receiver->length, and go to fast array write. |
1021 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 1032 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
1022 Immediate(Smi::FromInt(1))); | 1033 Immediate(Smi::FromInt(1))); |
1023 __ jmp(&fast); | 1034 __ jmp(&fast); |
1024 | 1035 |
1025 // Array case: Get the length and the elements array from the JS | 1036 // Array case: Get the length and the elements array from the JS |
1026 // array. Check that the array is in fast mode; if it is the | 1037 // array. Check that the array is in fast mode (and writable); if it |
1027 // length is always a smi. | 1038 // is the length is always a smi. |
1028 __ bind(&array); | 1039 __ bind(&array); |
1029 // eax: value | 1040 // eax: value |
1030 // edx: receiver, a JSArray | 1041 // edx: receiver, a JSArray |
1031 // ecx: key, a smi. | 1042 // ecx: key, a smi. |
1032 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 1043 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
1033 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 1044 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
1034 | 1045 |
1035 // Check the key against the length in the array, compute the | 1046 // Check the key against the length in the array, compute the |
1036 // address to store into and fall through to fast case. | 1047 // address to store into and fall through to fast case. |
1037 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. | 1048 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
(...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 | 1876 |
1866 // Check that the receiver isn't a smi. | 1877 // Check that the receiver isn't a smi. |
1867 __ test(receiver, Immediate(kSmiTagMask)); | 1878 __ test(receiver, Immediate(kSmiTagMask)); |
1868 __ j(zero, &miss, not_taken); | 1879 __ j(zero, &miss, not_taken); |
1869 | 1880 |
1870 // Check that the object is a JS array. | 1881 // Check that the object is a JS array. |
1871 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 1882 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
1872 __ j(not_equal, &miss, not_taken); | 1883 __ j(not_equal, &miss, not_taken); |
1873 | 1884 |
1874 // Check that elements are FixedArray. | 1885 // Check that elements are FixedArray. |
| 1886 // We rely on StoreIC_ArrayLength below to deal with all types of |
| 1887 // fast elements (including COW). |
1875 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); | 1888 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
1876 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); | 1889 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
1877 __ j(not_equal, &miss, not_taken); | 1890 __ j(not_equal, &miss, not_taken); |
1878 | 1891 |
1879 // Check that value is a smi. | 1892 // Check that value is a smi. |
1880 __ test(value, Immediate(kSmiTagMask)); | 1893 __ test(value, Immediate(kSmiTagMask)); |
1881 __ j(not_zero, &miss, not_taken); | 1894 __ j(not_zero, &miss, not_taken); |
1882 | 1895 |
1883 // Prepare tail call to StoreIC_ArrayLength. | 1896 // Prepare tail call to StoreIC_ArrayLength. |
1884 __ pop(scratch); | 1897 __ pop(scratch); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1978 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1966 __ TailCallExternalReference(ref, 3, 1); | 1979 __ TailCallExternalReference(ref, 3, 1); |
1967 } | 1980 } |
1968 | 1981 |
1969 #undef __ | 1982 #undef __ |
1970 | 1983 |
1971 | 1984 |
1972 } } // namespace v8::internal | 1985 } } // namespace v8::internal |
1973 | 1986 |
1974 #endif // V8_TARGET_ARCH_IA32 | 1987 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |