| 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 |