| 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 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 // the object) | 1888 // the object) |
| 1889 __ movq(rcx, rax); | 1889 __ movq(rcx, rax); |
| 1890 __ movq(rcx, FieldOperand(rcx, Map::kInstanceDescriptorsOffset)); | 1890 __ movq(rcx, FieldOperand(rcx, Map::kInstanceDescriptorsOffset)); |
| 1891 // Get the bridge array held in the enumeration index field. | 1891 // Get the bridge array held in the enumeration index field. |
| 1892 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); | 1892 __ movq(rcx, FieldOperand(rcx, DescriptorArray::kEnumerationIndexOffset)); |
| 1893 // Get the cache from the bridge array. | 1893 // Get the cache from the bridge array. |
| 1894 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 1894 __ movq(rdx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
| 1895 | 1895 |
| 1896 frame_->EmitPush(rax); // <- slot 3 | 1896 frame_->EmitPush(rax); // <- slot 3 |
| 1897 frame_->EmitPush(rdx); // <- slot 2 | 1897 frame_->EmitPush(rdx); // <- slot 2 |
| 1898 __ movl(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); | 1898 __ movq(rax, FieldOperand(rdx, FixedArray::kLengthOffset)); |
| 1899 __ Integer32ToSmi(rax, rax); | |
| 1900 frame_->EmitPush(rax); // <- slot 1 | 1899 frame_->EmitPush(rax); // <- slot 1 |
| 1901 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0 | 1900 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0 |
| 1902 entry.Jump(); | 1901 entry.Jump(); |
| 1903 | 1902 |
| 1904 fixed_array.Bind(); | 1903 fixed_array.Bind(); |
| 1905 // rax: fixed array (result from call to Runtime::kGetPropertyNamesFast) | 1904 // rax: fixed array (result from call to Runtime::kGetPropertyNamesFast) |
| 1906 frame_->EmitPush(Smi::FromInt(0)); // <- slot 3 | 1905 frame_->EmitPush(Smi::FromInt(0)); // <- slot 3 |
| 1907 frame_->EmitPush(rax); // <- slot 2 | 1906 frame_->EmitPush(rax); // <- slot 2 |
| 1908 | 1907 |
| 1909 // Push the length of the array and the initial index onto the stack. | 1908 // Push the length of the array and the initial index onto the stack. |
| 1910 __ movl(rax, FieldOperand(rax, FixedArray::kLengthOffset)); | 1909 __ movq(rax, FieldOperand(rax, FixedArray::kLengthOffset)); |
| 1911 __ Integer32ToSmi(rax, rax); | |
| 1912 frame_->EmitPush(rax); // <- slot 1 | 1910 frame_->EmitPush(rax); // <- slot 1 |
| 1913 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0 | 1911 frame_->EmitPush(Smi::FromInt(0)); // <- slot 0 |
| 1914 | 1912 |
| 1915 // Condition. | 1913 // Condition. |
| 1916 entry.Bind(); | 1914 entry.Bind(); |
| 1917 // Grab the current frame's height for the break and continue | 1915 // Grab the current frame's height for the break and continue |
| 1918 // targets only after all the state is pushed on the frame. | 1916 // targets only after all the state is pushed on the frame. |
| 1919 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 1917 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1920 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | 1918 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 1921 | 1919 |
| (...skipping 2543 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4465 | 4463 |
| 4466 // Fill out the elements FixedArray. | 4464 // Fill out the elements FixedArray. |
| 4467 // rax: JSArray. | 4465 // rax: JSArray. |
| 4468 // rcx: FixedArray. | 4466 // rcx: FixedArray. |
| 4469 // rbx: Number of elements in array as int32. | 4467 // rbx: Number of elements in array as int32. |
| 4470 | 4468 |
| 4471 // Set map. | 4469 // Set map. |
| 4472 __ Move(FieldOperand(rcx, HeapObject::kMapOffset), | 4470 __ Move(FieldOperand(rcx, HeapObject::kMapOffset), |
| 4473 Factory::fixed_array_map()); | 4471 Factory::fixed_array_map()); |
| 4474 // Set length. | 4472 // Set length. |
| 4475 __ movl(FieldOperand(rcx, FixedArray::kLengthOffset), rbx); | 4473 __ Integer32ToSmi(rdx, rbx); |
| 4474 __ movq(FieldOperand(rcx, FixedArray::kLengthOffset), rdx); |
| 4476 // Fill contents of fixed-array with the-hole. | 4475 // Fill contents of fixed-array with the-hole. |
| 4477 __ Move(rdx, Factory::the_hole_value()); | 4476 __ Move(rdx, Factory::the_hole_value()); |
| 4478 __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize)); | 4477 __ lea(rcx, FieldOperand(rcx, FixedArray::kHeaderSize)); |
| 4479 // Fill fixed array elements with hole. | 4478 // Fill fixed array elements with hole. |
| 4480 // rax: JSArray. | 4479 // rax: JSArray. |
| 4481 // rbx: Number of elements in array that remains to be filled, as int32. | 4480 // rbx: Number of elements in array that remains to be filled, as int32. |
| 4482 // rcx: Start of elements in FixedArray. | 4481 // rcx: Start of elements in FixedArray. |
| 4483 // rdx: the hole. | 4482 // rdx: the hole. |
| 4484 Label loop; | 4483 Label loop; |
| 4485 __ testl(rbx, rbx); | 4484 __ testl(rbx, rbx); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4584 __ InvokeFunction(rdi, expected, CALL_FUNCTION); | 4583 __ InvokeFunction(rdi, expected, CALL_FUNCTION); |
| 4585 | 4584 |
| 4586 // Find a place to put new cached value into. | 4585 // Find a place to put new cached value into. |
| 4587 Label add_new_entry, update_cache; | 4586 Label add_new_entry, update_cache; |
| 4588 __ movq(rcx, Operand(rsp, kPointerSize)); // restore the cache | 4587 __ movq(rcx, Operand(rsp, kPointerSize)); // restore the cache |
| 4589 // Possible optimization: cache size is constant for the given cache | 4588 // Possible optimization: cache size is constant for the given cache |
| 4590 // so technically we could use a constant here. However, if we have | 4589 // so technically we could use a constant here. However, if we have |
| 4591 // cache miss this optimization would hardly matter much. | 4590 // cache miss this optimization would hardly matter much. |
| 4592 | 4591 |
| 4593 // Check if we could add new entry to cache. | 4592 // Check if we could add new entry to cache. |
| 4594 __ movl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | 4593 __ movq(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); |
| 4595 __ movq(r9, FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset)); | 4594 __ movq(r9, FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset)); |
| 4596 __ SmiToInteger32(r9, r9); | 4595 __ SmiCompare(rbx, r9); |
| 4597 __ cmpq(rbx, r9); | |
| 4598 __ j(greater, &add_new_entry); | 4596 __ j(greater, &add_new_entry); |
| 4599 | 4597 |
| 4600 // Check if we could evict entry after finger. | 4598 // Check if we could evict entry after finger. |
| 4601 __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset)); | 4599 __ movq(rdx, FieldOperand(rcx, JSFunctionResultCache::kFingerOffset)); |
| 4602 __ SmiToInteger32(rdx, rdx); | 4600 __ SmiToInteger32(rdx, rdx); |
| 4601 __ SmiToInteger32(rbx, rbx); |
| 4603 __ addq(rdx, kEntrySizeImm); | 4602 __ addq(rdx, kEntrySizeImm); |
| 4604 Label forward; | 4603 Label forward; |
| 4605 __ cmpq(rbx, rdx); | 4604 __ cmpq(rbx, rdx); |
| 4606 __ j(greater, &forward); | 4605 __ j(greater, &forward); |
| 4607 // Need to wrap over the cache. | 4606 // Need to wrap over the cache. |
| 4608 __ movq(rdx, kEntriesIndexImm); | 4607 __ movq(rdx, kEntriesIndexImm); |
| 4609 __ bind(&forward); | 4608 __ bind(&forward); |
| 4610 __ Integer32ToSmi(r9, rdx); | 4609 __ Integer32ToSmi(r9, rdx); |
| 4611 __ jmp(&update_cache); | 4610 __ jmp(&update_cache); |
| 4612 | 4611 |
| 4613 __ bind(&add_new_entry); | 4612 __ bind(&add_new_entry); |
| 4614 // r9 holds cache size as int. | 4613 // r9 holds cache size as smi. |
| 4615 __ movq(rdx, r9); | 4614 __ SmiToInteger32(rdx, r9); |
| 4616 __ Integer32ToSmi(r9, r9); | |
| 4617 __ SmiAddConstant(rbx, r9, Smi::FromInt(JSFunctionResultCache::kEntrySize)); | 4615 __ SmiAddConstant(rbx, r9, Smi::FromInt(JSFunctionResultCache::kEntrySize)); |
| 4618 __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx); | 4616 __ movq(FieldOperand(rcx, JSFunctionResultCache::kCacheSizeOffset), rbx); |
| 4619 | 4617 |
| 4620 // Update the cache itself. | 4618 // Update the cache itself. |
| 4621 // rdx holds the index as int. | 4619 // rdx holds the index as int. |
| 4622 // r9 holds the index as smi. | 4620 // r9 holds the index as smi. |
| 4623 __ bind(&update_cache); | 4621 __ bind(&update_cache); |
| 4624 __ pop(rbx); // restore the key | 4622 __ pop(rbx); // restore the key |
| 4625 __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9); | 4623 __ movq(FieldOperand(rcx, JSFunctionResultCache::kFingerOffset), r9); |
| 4626 // Store key. | 4624 // Store key. |
| (...skipping 2537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7164 Result key = frame_->Pop(); | 7162 Result key = frame_->Pop(); |
| 7165 Result receiver = frame_->Pop(); | 7163 Result receiver = frame_->Pop(); |
| 7166 key.ToRegister(); | 7164 key.ToRegister(); |
| 7167 receiver.ToRegister(); | 7165 receiver.ToRegister(); |
| 7168 | 7166 |
| 7169 // Use a fresh temporary to load the elements without destroying | 7167 // Use a fresh temporary to load the elements without destroying |
| 7170 // the receiver which is needed for the deferred slow case. | 7168 // the receiver which is needed for the deferred slow case. |
| 7171 Result elements = allocator()->Allocate(); | 7169 Result elements = allocator()->Allocate(); |
| 7172 ASSERT(elements.is_valid()); | 7170 ASSERT(elements.is_valid()); |
| 7173 | 7171 |
| 7174 // Use a fresh temporary for the index and later the loaded | |
| 7175 // value. | |
| 7176 Result index = allocator()->Allocate(); | |
| 7177 ASSERT(index.is_valid()); | |
| 7178 | |
| 7179 DeferredReferenceGetKeyedValue* deferred = | 7172 DeferredReferenceGetKeyedValue* deferred = |
| 7180 new DeferredReferenceGetKeyedValue(index.reg(), | 7173 new DeferredReferenceGetKeyedValue(elements.reg(), |
| 7181 receiver.reg(), | 7174 receiver.reg(), |
| 7182 key.reg(), | 7175 key.reg(), |
| 7183 is_global); | 7176 is_global); |
| 7184 | 7177 |
| 7185 // Check that the receiver is not a smi (only needed if this | 7178 // Check that the receiver is not a smi (only needed if this |
| 7186 // is not a load from the global context) and that it has the | 7179 // is not a load from the global context) and that it has the |
| 7187 // expected map. | 7180 // expected map. |
| 7188 if (!is_global) { | 7181 if (!is_global) { |
| 7189 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); | 7182 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); |
| 7190 } | 7183 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7206 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label()); | 7199 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label()); |
| 7207 | 7200 |
| 7208 // Get the elements array from the receiver and check that it | 7201 // Get the elements array from the receiver and check that it |
| 7209 // is not a dictionary. | 7202 // is not a dictionary. |
| 7210 __ movq(elements.reg(), | 7203 __ movq(elements.reg(), |
| 7211 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); | 7204 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); |
| 7212 __ Cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), | 7205 __ Cmp(FieldOperand(elements.reg(), HeapObject::kMapOffset), |
| 7213 Factory::fixed_array_map()); | 7206 Factory::fixed_array_map()); |
| 7214 deferred->Branch(not_equal); | 7207 deferred->Branch(not_equal); |
| 7215 | 7208 |
| 7216 // Shift the key to get the actual index value and check that | 7209 // Check that key is within bounds. |
| 7217 // it is within bounds. | 7210 __ SmiCompare(key.reg(), |
| 7218 __ SmiToInteger32(index.reg(), key.reg()); | 7211 FieldOperand(elements.reg(), FixedArray::kLengthOffset)); |
| 7219 __ cmpl(index.reg(), | |
| 7220 FieldOperand(elements.reg(), FixedArray::kLengthOffset)); | |
| 7221 deferred->Branch(above_equal); | 7212 deferred->Branch(above_equal); |
| 7222 | 7213 |
| 7223 // The index register holds the un-smi-tagged key. It has been | 7214 // The key register holds the smi-tagged key. Load the value and |
| 7224 // zero-extended to 64-bits, so it can be used directly as index in the | 7215 // check that it is not the hole value. |
| 7225 // operand below. | 7216 Result value = elements; |
| 7226 // Load and check that the result is not the hole. We could | 7217 SmiIndex index = |
| 7227 // reuse the index or elements register for the value. | 7218 masm_->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); |
| 7228 // | |
| 7229 // TODO(206): Consider whether it makes sense to try some | |
| 7230 // heuristic about which register to reuse. For example, if | |
| 7231 // one is rax, the we can reuse that one because the value | |
| 7232 // coming from the deferred code will be in rax. | |
| 7233 Result value = index; | |
| 7234 __ movq(value.reg(), | 7219 __ movq(value.reg(), |
| 7235 Operand(elements.reg(), | 7220 FieldOperand(elements.reg(), |
| 7236 index.reg(), | 7221 index.reg, |
| 7237 times_pointer_size, | 7222 index.scale, |
| 7238 FixedArray::kHeaderSize - kHeapObjectTag)); | 7223 FixedArray::kHeaderSize)); |
| 7239 elements.Unuse(); | |
| 7240 index.Unuse(); | |
| 7241 __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex); | 7224 __ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex); |
| 7242 deferred->Branch(equal); | 7225 deferred->Branch(equal); |
| 7243 __ IncrementCounter(&Counters::keyed_load_inline, 1); | 7226 __ IncrementCounter(&Counters::keyed_load_inline, 1); |
| 7244 | 7227 |
| 7245 deferred->BindExit(); | 7228 deferred->BindExit(); |
| 7246 // Restore the receiver and key to the frame and push the | 7229 // Restore the receiver and key to the frame and push the |
| 7247 // result on top of it. | 7230 // result on top of it. |
| 7248 frame_->Push(&receiver); | 7231 frame_->Push(&receiver); |
| 7249 frame_->Push(&key); | 7232 frame_->Push(&key); |
| 7250 return value; | 7233 return value; |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7529 key.reg()); | 7512 key.reg()); |
| 7530 deferred->Branch(below_equal); | 7513 deferred->Branch(below_equal); |
| 7531 | 7514 |
| 7532 // Get the elements array from the receiver and check that it | 7515 // Get the elements array from the receiver and check that it |
| 7533 // is a flat array (not a dictionary). | 7516 // is a flat array (not a dictionary). |
| 7534 __ movq(tmp.reg(), | 7517 __ movq(tmp.reg(), |
| 7535 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); | 7518 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); |
| 7536 | 7519 |
| 7537 // Check whether it is possible to omit the write barrier. If the | 7520 // Check whether it is possible to omit the write barrier. If the |
| 7538 // elements array is in new space or the value written is a smi we can | 7521 // elements array is in new space or the value written is a smi we can |
| 7539 // safely update the elements array without updating the remembered set. | 7522 // safely update the elements array without write barrier. |
| 7540 Label in_new_space; | 7523 Label in_new_space; |
| 7541 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space); | 7524 __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space); |
| 7542 if (!value_is_constant) { | 7525 if (!value_is_constant) { |
| 7543 __ JumpIfNotSmi(value.reg(), deferred->entry_label()); | 7526 __ JumpIfNotSmi(value.reg(), deferred->entry_label()); |
| 7544 } | 7527 } |
| 7545 | 7528 |
| 7546 __ bind(&in_new_space); | 7529 __ bind(&in_new_space); |
| 7547 // Bind the deferred code patch site to be able to locate the | 7530 // Bind the deferred code patch site to be able to locate the |
| 7548 // fixed array map comparison. When debugging, we patch this | 7531 // fixed array map comparison. When debugging, we patch this |
| 7549 // comparison to always fail so that we will hit the IC call | 7532 // comparison to always fail so that we will hit the IC call |
| 7550 // in the deferred code which will allow the debugger to | 7533 // in the deferred code which will allow the debugger to |
| 7551 // break for fast case stores. | 7534 // break for fast case stores. |
| 7552 __ bind(deferred->patch_site()); | 7535 __ bind(deferred->patch_site()); |
| 7553 // Avoid using __ to ensure the distance from patch_site | 7536 // Avoid using __ to ensure the distance from patch_site |
| 7554 // to the map address is always the same. | 7537 // to the map address is always the same. |
| 7555 masm->movq(kScratchRegister, Factory::fixed_array_map(), | 7538 masm->movq(kScratchRegister, Factory::fixed_array_map(), |
| 7556 RelocInfo::EMBEDDED_OBJECT); | 7539 RelocInfo::EMBEDDED_OBJECT); |
| 7557 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset), | 7540 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset), |
| 7558 kScratchRegister); | 7541 kScratchRegister); |
| 7559 deferred->Branch(not_equal); | 7542 deferred->Branch(not_equal); |
| 7560 | 7543 |
| 7561 // Store the value. | 7544 // Store the value. |
| 7562 SmiIndex index = | 7545 SmiIndex index = |
| 7563 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); | 7546 masm->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); |
| 7564 __ movq(Operand(tmp.reg(), | 7547 __ movq(FieldOperand(tmp.reg(), |
| 7565 index.reg, | 7548 index.reg, |
| 7566 index.scale, | 7549 index.scale, |
| 7567 FixedArray::kHeaderSize - kHeapObjectTag), | 7550 FixedArray::kHeaderSize), |
| 7568 value.reg()); | 7551 value.reg()); |
| 7569 __ IncrementCounter(&Counters::keyed_store_inline, 1); | 7552 __ IncrementCounter(&Counters::keyed_store_inline, 1); |
| 7570 | 7553 |
| 7571 deferred->BindExit(); | 7554 deferred->BindExit(); |
| 7572 | 7555 |
| 7573 cgen_->frame()->Push(&value); | 7556 cgen_->frame()->Push(&value); |
| 7574 } else { | 7557 } else { |
| 7575 Result answer = cgen_->frame()->CallKeyedStoreIC(); | 7558 Result answer = cgen_->frame()->CallKeyedStoreIC(); |
| 7576 // Make sure that we do not have a test instruction after the | 7559 // Make sure that we do not have a test instruction after the |
| 7577 // call. A test instruction after the call is used to | 7560 // call. A test instruction after the call is used to |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7637 int length = slots_ + Context::MIN_CONTEXT_SLOTS; | 7620 int length = slots_ + Context::MIN_CONTEXT_SLOTS; |
| 7638 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, | 7621 __ AllocateInNewSpace((length * kPointerSize) + FixedArray::kHeaderSize, |
| 7639 rax, rbx, rcx, &gc, TAG_OBJECT); | 7622 rax, rbx, rcx, &gc, TAG_OBJECT); |
| 7640 | 7623 |
| 7641 // Get the function from the stack. | 7624 // Get the function from the stack. |
| 7642 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 7625 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| 7643 | 7626 |
| 7644 // Setup the object header. | 7627 // Setup the object header. |
| 7645 __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); | 7628 __ LoadRoot(kScratchRegister, Heap::kContextMapRootIndex); |
| 7646 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); | 7629 __ movq(FieldOperand(rax, HeapObject::kMapOffset), kScratchRegister); |
| 7647 __ movl(FieldOperand(rax, Array::kLengthOffset), Immediate(length)); | 7630 __ Move(FieldOperand(rax, FixedArray::kLengthOffset), Smi::FromInt(length)); |
| 7648 | 7631 |
| 7649 // Setup the fixed slots. | 7632 // Setup the fixed slots. |
| 7650 __ xor_(rbx, rbx); // Set to NULL. | 7633 __ xor_(rbx, rbx); // Set to NULL. |
| 7651 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); | 7634 __ movq(Operand(rax, Context::SlotOffset(Context::CLOSURE_INDEX)), rcx); |
| 7652 __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax); | 7635 __ movq(Operand(rax, Context::SlotOffset(Context::FCONTEXT_INDEX)), rax); |
| 7653 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx); | 7636 __ movq(Operand(rax, Context::SlotOffset(Context::PREVIOUS_INDEX)), rbx); |
| 7654 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx); | 7637 __ movq(Operand(rax, Context::SlotOffset(Context::EXTENSION_INDEX)), rbx); |
| 7655 | 7638 |
| 7656 // Copy the global object from the surrounding context. | 7639 // Copy the global object from the surrounding context. |
| 7657 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 7640 __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8312 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); | 8295 __ CmpObjectType(rax, JS_ARRAY_TYPE, kScratchRegister); |
| 8313 __ j(not_equal, &runtime); | 8296 __ j(not_equal, &runtime); |
| 8314 // Check that the JSArray is in fast case. | 8297 // Check that the JSArray is in fast case. |
| 8315 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); | 8298 __ movq(rbx, FieldOperand(rax, JSArray::kElementsOffset)); |
| 8316 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); | 8299 __ movq(rax, FieldOperand(rbx, HeapObject::kMapOffset)); |
| 8317 __ Cmp(rax, Factory::fixed_array_map()); | 8300 __ Cmp(rax, Factory::fixed_array_map()); |
| 8318 __ j(not_equal, &runtime); | 8301 __ j(not_equal, &runtime); |
| 8319 // Check that the last match info has space for the capture registers and the | 8302 // Check that the last match info has space for the capture registers and the |
| 8320 // additional information. Ensure no overflow in add. | 8303 // additional information. Ensure no overflow in add. |
| 8321 ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); | 8304 ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); |
| 8322 __ movl(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); | 8305 __ movq(rax, FieldOperand(rbx, FixedArray::kLengthOffset)); |
| 8306 __ SmiToInteger32(rax, rax); |
| 8323 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); | 8307 __ addl(rdx, Immediate(RegExpImpl::kLastMatchOverhead)); |
| 8324 __ cmpl(rdx, rax); | 8308 __ cmpl(rdx, rax); |
| 8325 __ j(greater, &runtime); | 8309 __ j(greater, &runtime); |
| 8326 | 8310 |
| 8327 // ecx: RegExp data (FixedArray) | 8311 // ecx: RegExp data (FixedArray) |
| 8328 // Check the representation and encoding of the subject string. | 8312 // Check the representation and encoding of the subject string. |
| 8329 Label seq_string, seq_two_byte_string, check_code; | 8313 Label seq_string, seq_two_byte_string, check_code; |
| 8330 const int kStringRepresentationEncodingMask = | 8314 const int kStringRepresentationEncodingMask = |
| 8331 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 8315 kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |
| 8332 __ movq(rax, Operand(rsp, kSubjectOffset)); | 8316 __ movq(rax, Operand(rsp, kSubjectOffset)); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8590 // Use of registers. Register result is used as a temporary. | 8574 // Use of registers. Register result is used as a temporary. |
| 8591 Register number_string_cache = result; | 8575 Register number_string_cache = result; |
| 8592 Register mask = scratch1; | 8576 Register mask = scratch1; |
| 8593 Register scratch = scratch2; | 8577 Register scratch = scratch2; |
| 8594 | 8578 |
| 8595 // Load the number string cache. | 8579 // Load the number string cache. |
| 8596 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); | 8580 __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); |
| 8597 | 8581 |
| 8598 // Make the hash mask from the length of the number string cache. It | 8582 // Make the hash mask from the length of the number string cache. It |
| 8599 // contains two elements (number and string) for each cache entry. | 8583 // contains two elements (number and string) for each cache entry. |
| 8600 __ movl(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); | 8584 __ movq(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); |
| 8601 __ shrl(mask, Immediate(1)); // Divide length by two (length is not a smi). | 8585 // Divide smi tagged length by two. |
| 8602 __ subl(mask, Immediate(1)); // Make mask. | 8586 __ PositiveSmiDivPowerOfTwoToInteger32(mask, mask, 1); |
| 8587 __ subq(mask, Immediate(1)); // Make mask. |
| 8603 | 8588 |
| 8604 // Calculate the entry in the number string cache. The hash value in the | 8589 // Calculate the entry in the number string cache. The hash value in the |
| 8605 // number string cache for smis is just the smi value, and the hash for | 8590 // number string cache for smis is just the smi value, and the hash for |
| 8606 // doubles is the xor of the upper and lower words. See | 8591 // doubles is the xor of the upper and lower words. See |
| 8607 // Heap::GetNumberStringCache. | 8592 // Heap::GetNumberStringCache. |
| 8608 Label is_smi; | 8593 Label is_smi; |
| 8609 Label load_result_from_cache; | 8594 Label load_result_from_cache; |
| 8610 if (!object_is_smi) { | 8595 if (!object_is_smi) { |
| 8611 __ JumpIfSmi(object, &is_smi); | 8596 __ JumpIfSmi(object, &is_smi); |
| 8612 __ CheckMap(object, Factory::heap_number_map(), not_found, true); | 8597 __ CheckMap(object, Factory::heap_number_map(), not_found, true); |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9112 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); | 9097 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); |
| 9113 __ movq(FieldOperand(rax, JSObject::kHeaderSize + kPointerSize), rcx); | 9098 __ movq(FieldOperand(rax, JSObject::kHeaderSize + kPointerSize), rcx); |
| 9114 | 9099 |
| 9115 // If there are no actual arguments, we're done. | 9100 // If there are no actual arguments, we're done. |
| 9116 Label done; | 9101 Label done; |
| 9117 __ testq(rcx, rcx); | 9102 __ testq(rcx, rcx); |
| 9118 __ j(zero, &done); | 9103 __ j(zero, &done); |
| 9119 | 9104 |
| 9120 // Get the parameters pointer from the stack and untag the length. | 9105 // Get the parameters pointer from the stack and untag the length. |
| 9121 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | 9106 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); |
| 9122 __ SmiToInteger32(rcx, rcx); | |
| 9123 | 9107 |
| 9124 // Setup the elements pointer in the allocated arguments object and | 9108 // Setup the elements pointer in the allocated arguments object and |
| 9125 // initialize the header in the elements fixed array. | 9109 // initialize the header in the elements fixed array. |
| 9126 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); | 9110 __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize)); |
| 9127 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 9111 __ movq(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
| 9128 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | 9112 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
| 9129 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 9113 __ movq(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| 9130 __ movl(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | 9114 __ movq(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
| 9115 __ SmiToInteger32(rcx, rcx); // Untag length for the loop below. |
| 9131 | 9116 |
| 9132 // Copy the fixed array slots. | 9117 // Copy the fixed array slots. |
| 9133 Label loop; | 9118 Label loop; |
| 9134 __ bind(&loop); | 9119 __ bind(&loop); |
| 9135 __ movq(kScratchRegister, Operand(rdx, -1 * kPointerSize)); // Skip receiver. | 9120 __ movq(kScratchRegister, Operand(rdx, -1 * kPointerSize)); // Skip receiver. |
| 9136 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), kScratchRegister); | 9121 __ movq(FieldOperand(rdi, FixedArray::kHeaderSize), kScratchRegister); |
| 9137 __ addq(rdi, Immediate(kPointerSize)); | 9122 __ addq(rdi, Immediate(kPointerSize)); |
| 9138 __ subq(rdx, Immediate(kPointerSize)); | 9123 __ subq(rdx, Immediate(kPointerSize)); |
| 9139 __ decq(rcx); | 9124 __ decq(rcx); |
| 9140 __ j(not_zero, &loop); | 9125 __ j(not_zero, &loop); |
| (...skipping 1750 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10891 __ movl(rcx, r8); | 10876 __ movl(rcx, r8); |
| 10892 __ and_(rcx, r9); | 10877 __ and_(rcx, r9); |
| 10893 ASSERT(kStringEncodingMask == kAsciiStringTag); | 10878 ASSERT(kStringEncodingMask == kAsciiStringTag); |
| 10894 __ testl(rcx, Immediate(kAsciiStringTag)); | 10879 __ testl(rcx, Immediate(kAsciiStringTag)); |
| 10895 __ j(zero, &non_ascii); | 10880 __ j(zero, &non_ascii); |
| 10896 // Allocate an acsii cons string. | 10881 // Allocate an acsii cons string. |
| 10897 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); | 10882 __ AllocateAsciiConsString(rcx, rdi, no_reg, &string_add_runtime); |
| 10898 __ bind(&allocated); | 10883 __ bind(&allocated); |
| 10899 // Fill the fields of the cons string. | 10884 // Fill the fields of the cons string. |
| 10900 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); | 10885 __ movq(FieldOperand(rcx, ConsString::kLengthOffset), rbx); |
| 10901 __ movl(FieldOperand(rcx, ConsString::kHashFieldOffset), | 10886 __ movq(FieldOperand(rcx, ConsString::kHashFieldOffset), |
| 10902 Immediate(String::kEmptyHashField)); | 10887 Immediate(String::kEmptyHashField)); |
| 10903 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); | 10888 __ movq(FieldOperand(rcx, ConsString::kFirstOffset), rax); |
| 10904 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); | 10889 __ movq(FieldOperand(rcx, ConsString::kSecondOffset), rdx); |
| 10905 __ movq(rax, rcx); | 10890 __ movq(rax, rcx); |
| 10906 __ IncrementCounter(&Counters::string_add_native, 1); | 10891 __ IncrementCounter(&Counters::string_add_native, 1); |
| 10907 __ ret(2 * kPointerSize); | 10892 __ ret(2 * kPointerSize); |
| 10908 __ bind(&non_ascii); | 10893 __ bind(&non_ascii); |
| 10909 // Allocate a two byte cons string. | 10894 // Allocate a two byte cons string. |
| 10910 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); | 10895 __ AllocateConsString(rcx, rdi, no_reg, &string_add_runtime); |
| 10911 __ jmp(&allocated); | 10896 __ jmp(&allocated); |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11629 } | 11614 } |
| 11630 | 11615 |
| 11631 #endif | 11616 #endif |
| 11632 | 11617 |
| 11633 | 11618 |
| 11634 #undef __ | 11619 #undef __ |
| 11635 | 11620 |
| 11636 } } // namespace v8::internal | 11621 } } // namespace v8::internal |
| 11637 | 11622 |
| 11638 #endif // V8_TARGET_ARCH_X64 | 11623 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |