OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 297 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
298 } | 298 } |
299 | 299 |
300 | 300 |
301 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 301 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
302 // ----------- S t a t e ------------- | 302 // ----------- S t a t e ------------- |
303 // -- eax : key | 303 // -- eax : key |
304 // -- edx : receiver | 304 // -- edx : receiver |
305 // -- esp[0] : return address | 305 // -- esp[0] : return address |
306 // ----------------------------------- | 306 // ----------------------------------- |
307 Label slow, check_string, index_smi, index_string; | 307 Label slow, check_string, index_int, index_string; |
308 Label check_pixel_array, probe_dictionary; | 308 Label check_pixel_array, probe_dictionary; |
309 Label check_number_dictionary; | 309 Label check_number_dictionary; |
310 | 310 |
311 // Check that the object isn't a smi. | 311 // Check that the object isn't a smi. |
312 __ test(edx, Immediate(kSmiTagMask)); | 312 __ test(edx, Immediate(kSmiTagMask)); |
313 __ j(zero, &slow, not_taken); | 313 __ j(zero, &slow, not_taken); |
314 | 314 |
315 // Get the map of the receiver. | 315 // Get the map of the receiver. |
316 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 316 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
317 | 317 |
318 // Check bit field. | 318 // Check bit field. |
319 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); | 319 __ movzx_b(ebx, FieldOperand(ecx, Map::kBitFieldOffset)); |
320 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); | 320 __ test(ebx, Immediate(kSlowCaseBitFieldMask)); |
321 __ j(not_zero, &slow, not_taken); | 321 __ j(not_zero, &slow, not_taken); |
322 // Check that the object is some kind of JS object EXCEPT JS Value type. | 322 // Check that the object is some kind of JS object EXCEPT JS Value type. |
323 // In the case that the object is a value-wrapper object, | 323 // In the case that the object is a value-wrapper object, |
324 // we enter the runtime system to make sure that indexing | 324 // we enter the runtime system to make sure that indexing |
325 // into string objects work as intended. | 325 // into string objects work as intended. |
326 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 326 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
327 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); | 327 __ CmpInstanceType(ecx, JS_OBJECT_TYPE); |
328 __ j(below, &slow, not_taken); | 328 __ j(below, &slow, not_taken); |
329 // Check that the key is a smi. | 329 // Check that the key is a smi. |
330 __ test(eax, Immediate(kSmiTagMask)); | 330 __ test(eax, Immediate(kSmiTagMask)); |
331 __ j(not_zero, &check_string, not_taken); | 331 __ j(not_zero, &check_string, not_taken); |
| 332 __ mov(ebx, eax); |
| 333 __ SmiUntag(ebx); |
332 // Get the elements array of the object. | 334 // Get the elements array of the object. |
333 __ bind(&index_smi); | 335 __ bind(&index_int); |
334 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 336 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
335 // Check that the object is in fast mode (not dictionary). | 337 // Check that the object is in fast mode (not dictionary). |
336 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); | 338 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); |
337 // Check that the key (index) is within bounds. | 339 // Check that the key (index) is within bounds. |
338 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); | 340 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |
339 __ j(above_equal, &slow); | 341 __ j(above_equal, &slow); |
340 // Fast case: Do the load. | 342 // Fast case: Do the load. |
341 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); | 343 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); |
342 __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize)); | |
343 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); | 344 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); |
344 // In case the loaded value is the_hole we have to consult GetProperty | 345 // In case the loaded value is the_hole we have to consult GetProperty |
345 // to ensure the prototype chain is searched. | 346 // to ensure the prototype chain is searched. |
346 __ j(equal, &slow); | 347 __ j(equal, &slow); |
347 __ mov(eax, ecx); | 348 __ mov(eax, ecx); |
348 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 349 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
349 __ ret(0); | 350 __ ret(0); |
350 | 351 |
351 __ bind(&check_pixel_array); | 352 __ bind(&check_pixel_array); |
352 // Check whether the elements is a pixel array. | 353 // Check whether the elements is a pixel array. |
353 // edx: receiver | 354 // edx: receiver |
| 355 // ebx: untagged index |
354 // eax: key | 356 // eax: key |
355 // ecx: elements | 357 // ecx: elements |
356 __ mov(ebx, eax); | |
357 __ SmiUntag(ebx); | |
358 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); | 358 __ CheckMap(ecx, Factory::pixel_array_map(), &check_number_dictionary, true); |
359 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); | 359 __ cmp(ebx, FieldOperand(ecx, PixelArray::kLengthOffset)); |
360 __ j(above_equal, &slow); | 360 __ j(above_equal, &slow); |
361 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); | 361 __ mov(eax, FieldOperand(ecx, PixelArray::kExternalPointerOffset)); |
362 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); | 362 __ movzx_b(eax, Operand(eax, ebx, times_1, 0)); |
363 __ SmiTag(eax); | 363 __ SmiTag(eax); |
364 __ ret(0); | 364 __ ret(0); |
365 | 365 |
366 __ bind(&check_number_dictionary); | 366 __ bind(&check_number_dictionary); |
367 // Check whether the elements is a number dictionary. | 367 // Check whether the elements is a number dictionary. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 478 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
479 __ ret(0); | 479 __ ret(0); |
480 | 480 |
481 // If the hash field contains an array index pick it out. The assert checks | 481 // If the hash field contains an array index pick it out. The assert checks |
482 // that the constants for the maximum number of digits for an array index | 482 // that the constants for the maximum number of digits for an array index |
483 // cached in the hash field and the number of bits reserved for it does not | 483 // cached in the hash field and the number of bits reserved for it does not |
484 // conflict. | 484 // conflict. |
485 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 485 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
486 (1 << String::kArrayIndexValueBits)); | 486 (1 << String::kArrayIndexValueBits)); |
487 __ bind(&index_string); | 487 __ bind(&index_string); |
488 // We want the smi-tagged index in eax. kArrayIndexValueMask has zeros in | 488 __ and_(ebx, String::kArrayIndexHashMask); |
489 // the low kHashShift bits. | 489 __ shr(ebx, String::kHashShift); |
490 ASSERT(String::kHashShift >= kSmiTagSize); | 490 __ jmp(&index_int); |
491 __ and_(ebx, String::kArrayIndexValueMask); | |
492 __ shr(ebx, String::kHashShift - kSmiTagSize); | |
493 __ mov(eax, ebx); | |
494 __ jmp(&index_smi); | |
495 } | 491 } |
496 | 492 |
497 | 493 |
498 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 494 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
499 // ----------- S t a t e ------------- | 495 // ----------- S t a t e ------------- |
500 // -- eax : key (index) | 496 // -- eax : key (index) |
501 // -- edx : receiver | 497 // -- edx : receiver |
502 // -- esp[0] : return address | 498 // -- esp[0] : return address |
503 // ----------------------------------- | 499 // ----------------------------------- |
504 Label miss; | 500 Label miss; |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 785 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
790 __ j(below, &slow, not_taken); | 786 __ j(below, &slow, not_taken); |
791 | 787 |
792 // Object case: Check key against length in the elements array. | 788 // Object case: Check key against length in the elements array. |
793 // eax: value | 789 // eax: value |
794 // edx: JSObject | 790 // edx: JSObject |
795 // ecx: key (a smi) | 791 // ecx: key (a smi) |
796 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 792 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
797 // Check that the object is in fast mode (not dictionary). | 793 // Check that the object is in fast mode (not dictionary). |
798 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 794 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
799 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 795 __ mov(ebx, Operand(ecx)); |
| 796 __ SmiUntag(ebx); |
| 797 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
800 __ j(below, &fast, taken); | 798 __ j(below, &fast, taken); |
801 | 799 |
802 // Slow case: call runtime. | 800 // Slow case: call runtime. |
803 __ bind(&slow); | 801 __ bind(&slow); |
804 GenerateRuntimeSetProperty(masm); | 802 GenerateRuntimeSetProperty(masm); |
805 | 803 |
806 // Check whether the elements is a pixel array. | 804 // Check whether the elements is a pixel array. |
807 __ bind(&check_pixel_array); | 805 __ bind(&check_pixel_array); |
808 // eax: value | 806 // eax: value |
809 // ecx: key (a smi) | 807 // ecx: key |
810 // edx: receiver | 808 // edx: receiver |
811 // edi: elements array | 809 // edi: elements array |
812 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); | 810 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); |
813 // Check that the value is a smi. If a conversion is needed call into the | 811 // Check that the value is a smi. If a conversion is needed call into the |
814 // runtime to convert and clamp. | 812 // runtime to convert and clamp. |
815 __ test(eax, Immediate(kSmiTagMask)); | 813 __ test(eax, Immediate(kSmiTagMask)); |
816 __ j(not_zero, &slow); | 814 __ j(not_zero, &slow); |
817 __ mov(ebx, ecx); | 815 __ mov(ebx, ecx); |
818 __ SmiUntag(ebx); | 816 __ SmiUntag(ebx); |
819 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); | 817 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); |
(...skipping 15 matching lines...) Expand all Loading... |
835 // Extra capacity case: Check if there is extra capacity to | 833 // Extra capacity case: Check if there is extra capacity to |
836 // perform the store and update the length. Used for adding one | 834 // perform the store and update the length. Used for adding one |
837 // element to the array by writing to array[array.length]. | 835 // element to the array by writing to array[array.length]. |
838 __ bind(&extra); | 836 __ bind(&extra); |
839 // eax: value | 837 // eax: value |
840 // edx: receiver, a JSArray | 838 // edx: receiver, a JSArray |
841 // ecx: key, a smi. | 839 // ecx: key, a smi. |
842 // edi: receiver->elements, a FixedArray | 840 // edi: receiver->elements, a FixedArray |
843 // flags: compare (ecx, edx.length()) | 841 // flags: compare (ecx, edx.length()) |
844 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 842 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
845 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 843 __ mov(ebx, ecx); |
| 844 __ SmiUntag(ebx); // untag |
| 845 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); |
846 __ j(above_equal, &slow, not_taken); | 846 __ j(above_equal, &slow, not_taken); |
847 // Add 1 to receiver->length, and go to fast array write. | 847 // Add 1 to receiver->length, and go to fast array write. |
848 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 848 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
849 Immediate(Smi::FromInt(1))); | 849 Immediate(1 << kSmiTagSize)); |
850 __ jmp(&fast); | 850 __ jmp(&fast); |
851 | 851 |
852 // Array case: Get the length and the elements array from the JS | 852 // Array case: Get the length and the elements array from the JS |
853 // array. Check that the array is in fast mode; if it is the | 853 // array. Check that the array is in fast mode; if it is the |
854 // length is always a smi. | 854 // length is always a smi. |
855 __ bind(&array); | 855 __ bind(&array); |
856 // eax: value | 856 // eax: value |
857 // edx: receiver, a JSArray | 857 // edx: receiver, a JSArray |
858 // ecx: key, a smi. | 858 // ecx: key, a smi. |
859 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 859 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1640 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1640 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1641 __ TailCallExternalReference(ref, 3, 1); | 1641 __ TailCallExternalReference(ref, 3, 1); |
1642 } | 1642 } |
1643 | 1643 |
1644 #undef __ | 1644 #undef __ |
1645 | 1645 |
1646 | 1646 |
1647 } } // namespace v8::internal | 1647 } } // namespace v8::internal |
1648 | 1648 |
1649 #endif // V8_TARGET_ARCH_IA32 | 1649 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |