OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 if (i != kProbes - 1) { | 124 if (i != kProbes - 1) { |
125 __ j(equal, &done); | 125 __ j(equal, &done); |
126 } else { | 126 } else { |
127 __ j(not_equal, miss_label); | 127 __ j(not_equal, miss_label); |
128 } | 128 } |
129 } | 129 } |
130 | 130 |
131 // Check that the value is a normal property. | 131 // Check that the value is a normal property. |
132 __ bind(&done); | 132 __ bind(&done); |
133 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 133 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
134 __ testl(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), | 134 __ Test(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), |
135 Immediate(Smi::FromInt(PropertyDetails::TypeField::mask()))); | 135 Smi::FromInt(PropertyDetails::TypeField::mask())); |
136 __ j(not_zero, miss_label); | 136 __ j(not_zero, miss_label); |
137 | 137 |
138 // Get the value at the masked, scaled index. | 138 // Get the value at the masked, scaled index. |
139 const int kValueOffset = kElementsStartOffset + kPointerSize; | 139 const int kValueOffset = kElementsStartOffset + kPointerSize; |
140 __ movq(r1, | 140 __ movq(r1, |
141 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); | 141 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 // Helper function used to check that a value is either not an object | 145 // Helper function used to check that a value is either not an object |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 // Is the string an array index, with cached numeric value? | 329 // Is the string an array index, with cached numeric value? |
330 __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); | 330 __ movl(rbx, FieldOperand(rax, String::kLengthOffset)); |
331 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); | 331 __ testl(rbx, Immediate(String::kIsArrayIndexMask)); |
332 | 332 |
333 // If the string is a symbol, do a quick inline probe of the receiver's | 333 // If the string is a symbol, do a quick inline probe of the receiver's |
334 // dictionary, if it exists. | 334 // dictionary, if it exists. |
335 __ j(not_zero, &index_string); // The value in rbx is used at jump target. | 335 __ j(not_zero, &index_string); // The value in rbx is used at jump target. |
336 __ testb(FieldOperand(rdx, Map::kInstanceTypeOffset), | 336 __ testb(FieldOperand(rdx, Map::kInstanceTypeOffset), |
337 Immediate(kIsSymbolMask)); | 337 Immediate(kIsSymbolMask)); |
338 __ j(zero, &slow); | 338 __ j(zero, &slow); |
339 // Probe the dictionary leaving result in ecx. | 339 // Probe the dictionary leaving result in rcx. |
340 GenerateDictionaryLoad(masm, &slow, rbx, rcx, rdx, rax); | 340 GenerateDictionaryLoad(masm, &slow, rbx, rcx, rdx, rax); |
341 GenerateCheckNonObjectOrLoaded(masm, &slow, rcx); | 341 GenerateCheckNonObjectOrLoaded(masm, &slow, rcx); |
342 __ movq(rax, rcx); | 342 __ movq(rax, rcx); |
343 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); | 343 __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1); |
344 __ ret(0); | 344 __ ret(0); |
345 // Array index string: If short enough use cache in length/hash field (ebx). | 345 // Array index string: If short enough use cache in length/hash field (rbx). |
346 // We assert that there are enough bits in an int32_t after the hash shift | 346 // We assert that there are enough bits in an int32_t after the hash shift |
347 // bits have been subtracted to allow space for the length and the cached | 347 // bits have been subtracted to allow space for the length and the cached |
348 // array index. | 348 // array index. |
349 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < | 349 ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |
350 (1 << (String::kShortLengthShift - String::kHashShift))); | 350 (1 << (String::kShortLengthShift - String::kHashShift))); |
351 __ bind(&index_string); | 351 __ bind(&index_string); |
352 const int kLengthFieldLimit = | 352 const int kLengthFieldLimit = |
353 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; | 353 (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift; |
354 __ cmpl(rbx, Immediate(kLengthFieldLimit)); | 354 __ cmpl(rbx, Immediate(kLengthFieldLimit)); |
355 __ j(above_equal, &slow); | 355 __ j(above_equal, &slow); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 427 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
428 // Check that the receiver does not require access checks. We need | 428 // Check that the receiver does not require access checks. We need |
429 // to do this because this generic stub does not perform map checks. | 429 // to do this because this generic stub does not perform map checks. |
430 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 430 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
431 Immediate(1 << Map::kIsAccessCheckNeeded)); | 431 Immediate(1 << Map::kIsAccessCheckNeeded)); |
432 __ j(not_zero, &slow); | 432 __ j(not_zero, &slow); |
433 // Get the key from the stack. | 433 // Get the key from the stack. |
434 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address | 434 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address |
435 // Check that the key is a smi. | 435 // Check that the key is a smi. |
436 __ JumpIfNotSmi(rbx, &slow); | 436 __ JumpIfNotSmi(rbx, &slow); |
437 // If it is a smi, make sure it is zero-extended, so it can be | |
438 // used as an index in a memory operand. | |
439 __ movl(rbx, rbx); // Clear the high bits of rbx. | |
440 | 437 |
441 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); | 438 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); |
442 __ j(equal, &array); | 439 __ j(equal, &array); |
443 // Check that the object is some kind of JS object. | 440 // Check that the object is some kind of JS object. |
444 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); | 441 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); |
445 __ j(below, &slow); | 442 __ j(below, &slow); |
446 | 443 |
447 // Object case: Check key against length in the elements array. | 444 // Object case: Check key against length in the elements array. |
448 // rax: value | 445 // rax: value |
449 // rdx: JSObject | 446 // rdx: JSObject |
450 // rbx: index (as a smi), zero-extended. | 447 // rbx: index (as a smi) |
451 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 448 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
452 // Check that the object is in fast mode (not dictionary). | 449 // Check that the object is in fast mode (not dictionary). |
453 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), | 450 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
454 Heap::kFixedArrayMapRootIndex); | 451 Heap::kFixedArrayMapRootIndex); |
455 __ j(not_equal, &check_pixel_array); | 452 __ j(not_equal, &check_pixel_array); |
456 // Untag the key (for checking against untagged length in the fixed array). | 453 // Untag the key (for checking against untagged length in the fixed array). |
457 __ SmiToInteger32(rdx, rbx); | 454 __ SmiToInteger32(rdx, rbx); |
458 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); | 455 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); |
459 // rax: value | 456 // rax: value |
460 // rcx: FixedArray | 457 // rcx: FixedArray |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 __ ret(0); | 498 __ ret(0); |
502 | 499 |
503 // Extra capacity case: Check if there is extra capacity to | 500 // Extra capacity case: Check if there is extra capacity to |
504 // perform the store and update the length. Used for adding one | 501 // perform the store and update the length. Used for adding one |
505 // element to the array by writing to array[array.length]. | 502 // element to the array by writing to array[array.length]. |
506 __ bind(&extra); | 503 __ bind(&extra); |
507 // rax: value | 504 // rax: value |
508 // rdx: JSArray | 505 // rdx: JSArray |
509 // rcx: FixedArray | 506 // rcx: FixedArray |
510 // rbx: index (as a smi) | 507 // rbx: index (as a smi) |
511 // flags: compare (rbx, rdx.length()) | 508 // flags: smicompare (rdx.length(), rbx) |
512 __ j(not_equal, &slow); // do not leave holes in the array | 509 __ j(not_equal, &slow); // do not leave holes in the array |
513 __ SmiToInteger64(rbx, rbx); | 510 __ SmiToInteger64(rbx, rbx); |
514 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | 511 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); |
515 __ j(above_equal, &slow); | 512 __ j(above_equal, &slow); |
516 // Increment and restore smi-tag. | 513 // Increment and restore smi-tag. |
517 __ Integer64AddToSmi(rbx, rbx, 1); | 514 __ Integer64PlusConstantToSmi(rbx, rbx, 1); |
518 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); | 515 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); |
519 __ SmiSubConstant(rbx, rbx, 1, NULL); | 516 __ SmiSubConstant(rbx, rbx, Smi::FromInt(1)); |
520 __ jmp(&fast); | 517 __ jmp(&fast); |
521 | 518 |
522 // Array case: Get the length and the elements array from the JS | 519 // Array case: Get the length and the elements array from the JS |
523 // array. Check that the array is in fast mode; if it is the | 520 // array. Check that the array is in fast mode; if it is the |
524 // length is always a smi. | 521 // length is always a smi. |
525 __ bind(&array); | 522 __ bind(&array); |
526 // rax: value | 523 // rax: value |
527 // rdx: JSArray | 524 // rdx: JSArray |
528 // rbx: index (as a smi) | 525 // rbx: index (as a smi) |
529 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 526 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
530 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); | 527 __ CompareRoot(FieldOperand(rcx, HeapObject::kMapOffset), |
| 528 Heap::kFixedArrayMapRootIndex); |
531 __ j(not_equal, &slow); | 529 __ j(not_equal, &slow); |
532 | 530 |
533 // Check the key against the length in the array, compute the | 531 // Check the key against the length in the array, compute the |
534 // address to store into and fall through to fast case. | 532 // address to store into and fall through to fast case. |
535 __ cmpl(rbx, FieldOperand(rdx, JSArray::kLengthOffset)); | 533 __ SmiCompare(FieldOperand(rdx, JSArray::kLengthOffset), rbx); |
536 __ j(above_equal, &extra); | 534 __ j(below_equal, &extra); |
537 | 535 |
538 // Fast case: Do the store. | 536 // Fast case: Do the store. |
539 __ bind(&fast); | 537 __ bind(&fast); |
540 // rax: value | 538 // rax: value |
541 // rcx: FixedArray | 539 // rcx: FixedArray |
542 // rbx: index (as a smi) | 540 // rbx: index (as a smi) |
543 __ movq(Operand(rcx, rbx, times_half_pointer_size, | 541 Label non_smi_value; |
| 542 __ JumpIfNotSmi(rax, &non_smi_value); |
| 543 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); |
| 544 __ movq(Operand(rcx, index.reg, index.scale, |
544 FixedArray::kHeaderSize - kHeapObjectTag), | 545 FixedArray::kHeaderSize - kHeapObjectTag), |
545 rax); | 546 rax); |
| 547 __ ret(0); |
| 548 __ bind(&non_smi_value); |
| 549 // Slow case that needs to retain rbx for use by RecordWrite. |
546 // Update write barrier for the elements array address. | 550 // Update write barrier for the elements array address. |
| 551 SmiIndex index2 = masm->SmiToIndex(kScratchRegister, rbx, kPointerSizeLog2); |
| 552 __ movq(Operand(rcx, index2.reg, index2.scale, |
| 553 FixedArray::kHeaderSize - kHeapObjectTag), |
| 554 rax); |
547 __ movq(rdx, rax); | 555 __ movq(rdx, rax); |
548 __ RecordWrite(rcx, 0, rdx, rbx); | 556 __ RecordWriteNonSmi(rcx, 0, rdx, rbx); |
549 __ ret(0); | 557 __ ret(0); |
550 } | 558 } |
551 | 559 |
552 | 560 |
553 void CallIC::Generate(MacroAssembler* masm, | 561 void CallIC::Generate(MacroAssembler* masm, |
554 int argc, | 562 int argc, |
555 ExternalReference const& f) { | 563 ExternalReference const& f) { |
556 // Get the receiver of the function from the stack; 1 ~ return address. | 564 // Get the receiver of the function from the stack; 1 ~ return address. |
557 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 565 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
558 // Get the name of the function to call from the stack. | 566 // Get the name of the function to call from the stack. |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 | 1017 |
1010 // Cache miss: Jump to runtime. | 1018 // Cache miss: Jump to runtime. |
1011 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); | 1019 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); |
1012 } | 1020 } |
1013 | 1021 |
1014 | 1022 |
1015 #undef __ | 1023 #undef __ |
1016 | 1024 |
1017 | 1025 |
1018 } } // namespace v8::internal | 1026 } } // namespace v8::internal |
OLD | NEW |