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_int, index_string; | 307 Label slow, check_string, index_smi, 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); | |
334 // Get the elements array of the object. | 332 // Get the elements array of the object. |
335 __ bind(&index_int); | 333 __ bind(&index_smi); |
336 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); | 334 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); |
337 // Check that the object is in fast mode (not dictionary). | 335 // Check that the object is in fast mode (not dictionary). |
338 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); | 336 __ CheckMap(ecx, Factory::fixed_array_map(), &check_pixel_array, true); |
339 // Check that the key (index) is within bounds. | 337 // Check that the key (index) is within bounds. |
340 __ cmp(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); | 338 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); |
341 __ j(above_equal, &slow); | 339 __ j(above_equal, &slow); |
342 // Fast case: Do the load. | 340 // Fast case: Do the load. |
343 __ mov(ecx, FieldOperand(ecx, ebx, times_4, FixedArray::kHeaderSize)); | 341 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
| 342 __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize)); |
344 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); | 343 __ cmp(Operand(ecx), Immediate(Factory::the_hole_value())); |
345 // In case the loaded value is the_hole we have to consult GetProperty | 344 // In case the loaded value is the_hole we have to consult GetProperty |
346 // to ensure the prototype chain is searched. | 345 // to ensure the prototype chain is searched. |
347 __ j(equal, &slow); | 346 __ j(equal, &slow); |
348 __ mov(eax, ecx); | 347 __ mov(eax, ecx); |
349 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); | 348 __ IncrementCounter(&Counters::keyed_load_generic_smi, 1); |
350 __ ret(0); | 349 __ ret(0); |
351 | 350 |
352 __ bind(&check_pixel_array); | 351 __ bind(&check_pixel_array); |
353 // Check whether the elements is a pixel array. | 352 // Check whether the elements is a pixel array. |
354 // edx: receiver | 353 // edx: receiver |
355 // ebx: untagged index | |
356 // eax: key | 354 // eax: key |
357 // ecx: elements | 355 // 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 __ and_(ebx, String::kArrayIndexHashMask); | 488 // We want the smi-tagged index in eax. kArrayIndexValueMask has zeros in |
489 __ shr(ebx, String::kHashShift); | 489 // the low kHashShift bits. |
490 __ jmp(&index_int); | 490 ASSERT(String::kHashShift >= kSmiTagSize); |
| 491 __ and_(ebx, String::kArrayIndexValueMask); |
| 492 __ shr(ebx, String::kHashShift - kSmiTagSize); |
| 493 __ mov(eax, ebx); |
| 494 __ jmp(&index_smi); |
491 } | 495 } |
492 | 496 |
493 | 497 |
494 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { | 498 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { |
495 // ----------- S t a t e ------------- | 499 // ----------- S t a t e ------------- |
496 // -- eax : key (index) | 500 // -- eax : key (index) |
497 // -- edx : receiver | 501 // -- edx : receiver |
498 // -- esp[0] : return address | 502 // -- esp[0] : return address |
499 // ----------------------------------- | 503 // ----------------------------------- |
500 Label miss; | 504 Label miss; |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 758 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
755 __ j(below, &slow, not_taken); | 759 __ j(below, &slow, not_taken); |
756 | 760 |
757 // Object case: Check key against length in the elements array. | 761 // Object case: Check key against length in the elements array. |
758 // eax: value | 762 // eax: value |
759 // edx: JSObject | 763 // edx: JSObject |
760 // ecx: key (a smi) | 764 // ecx: key (a smi) |
761 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 765 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
762 // Check that the object is in fast mode (not dictionary). | 766 // Check that the object is in fast mode (not dictionary). |
763 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); | 767 __ CheckMap(edi, Factory::fixed_array_map(), &check_pixel_array, true); |
764 __ mov(ebx, Operand(ecx)); | 768 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
765 __ SmiUntag(ebx); | |
766 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | |
767 __ j(below, &fast, taken); | 769 __ j(below, &fast, taken); |
768 | 770 |
769 // Slow case: call runtime. | 771 // Slow case: call runtime. |
770 __ bind(&slow); | 772 __ bind(&slow); |
771 GenerateRuntimeSetProperty(masm); | 773 GenerateRuntimeSetProperty(masm); |
772 | 774 |
773 // Check whether the elements is a pixel array. | 775 // Check whether the elements is a pixel array. |
774 __ bind(&check_pixel_array); | 776 __ bind(&check_pixel_array); |
775 // eax: value | 777 // eax: value |
776 // ecx: key | 778 // ecx: key (a smi) |
777 // edx: receiver | 779 // edx: receiver |
778 // edi: elements array | 780 // edi: elements array |
779 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); | 781 __ CheckMap(edi, Factory::pixel_array_map(), &slow, true); |
780 // Check that the value is a smi. If a conversion is needed call into the | 782 // Check that the value is a smi. If a conversion is needed call into the |
781 // runtime to convert and clamp. | 783 // runtime to convert and clamp. |
782 __ test(eax, Immediate(kSmiTagMask)); | 784 __ test(eax, Immediate(kSmiTagMask)); |
783 __ j(not_zero, &slow); | 785 __ j(not_zero, &slow); |
784 __ mov(ebx, ecx); | 786 __ mov(ebx, ecx); |
785 __ SmiUntag(ebx); | 787 __ SmiUntag(ebx); |
786 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); | 788 __ cmp(ebx, FieldOperand(edi, PixelArray::kLengthOffset)); |
(...skipping 15 matching lines...) Expand all Loading... |
802 // Extra capacity case: Check if there is extra capacity to | 804 // Extra capacity case: Check if there is extra capacity to |
803 // perform the store and update the length. Used for adding one | 805 // perform the store and update the length. Used for adding one |
804 // element to the array by writing to array[array.length]. | 806 // element to the array by writing to array[array.length]. |
805 __ bind(&extra); | 807 __ bind(&extra); |
806 // eax: value | 808 // eax: value |
807 // edx: receiver, a JSArray | 809 // edx: receiver, a JSArray |
808 // ecx: key, a smi. | 810 // ecx: key, a smi. |
809 // edi: receiver->elements, a FixedArray | 811 // edi: receiver->elements, a FixedArray |
810 // flags: compare (ecx, edx.length()) | 812 // flags: compare (ecx, edx.length()) |
811 __ j(not_equal, &slow, not_taken); // do not leave holes in the array | 813 __ j(not_equal, &slow, not_taken); // do not leave holes in the array |
812 __ mov(ebx, ecx); | 814 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
813 __ SmiUntag(ebx); // untag | |
814 __ cmp(ebx, FieldOperand(edi, Array::kLengthOffset)); | |
815 __ j(above_equal, &slow, not_taken); | 815 __ j(above_equal, &slow, not_taken); |
816 // Add 1 to receiver->length, and go to fast array write. | 816 // Add 1 to receiver->length, and go to fast array write. |
817 __ add(FieldOperand(edx, JSArray::kLengthOffset), | 817 __ add(FieldOperand(edx, JSArray::kLengthOffset), |
818 Immediate(1 << kSmiTagSize)); | 818 Immediate(Smi::FromInt(1))); |
819 __ jmp(&fast); | 819 __ jmp(&fast); |
820 | 820 |
821 // Array case: Get the length and the elements array from the JS | 821 // Array case: Get the length and the elements array from the JS |
822 // array. Check that the array is in fast mode; if it is the | 822 // array. Check that the array is in fast mode; if it is the |
823 // length is always a smi. | 823 // length is always a smi. |
824 __ bind(&array); | 824 __ bind(&array); |
825 // eax: value | 825 // eax: value |
826 // edx: receiver, a JSArray | 826 // edx: receiver, a JSArray |
827 // ecx: key, a smi. | 827 // ecx: key, a smi. |
828 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 828 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
(...skipping 780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1609 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | 1609 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
1610 __ TailCallExternalReference(ref, 3, 1); | 1610 __ TailCallExternalReference(ref, 3, 1); |
1611 } | 1611 } |
1612 | 1612 |
1613 #undef __ | 1613 #undef __ |
1614 | 1614 |
1615 | 1615 |
1616 } } // namespace v8::internal | 1616 } } // namespace v8::internal |
1617 | 1617 |
1618 #endif // V8_TARGET_ARCH_IA32 | 1618 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |