Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 for (int i = 0; i < num_parameters; i++) { | 187 for (int i = 0; i < num_parameters; i++) { |
| 188 Slot* slot = scope()->parameter(i)->AsSlot(); | 188 Slot* slot = scope()->parameter(i)->AsSlot(); |
| 189 if (slot != NULL && slot->type() == Slot::CONTEXT) { | 189 if (slot != NULL && slot->type() == Slot::CONTEXT) { |
| 190 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 190 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
| 191 (num_parameters - 1 - i) * kPointerSize; | 191 (num_parameters - 1 - i) * kPointerSize; |
| 192 // Load parameter from stack. | 192 // Load parameter from stack. |
| 193 __ movq(rax, Operand(rbp, parameter_offset)); | 193 __ movq(rax, Operand(rbp, parameter_offset)); |
| 194 // Store it in the context. | 194 // Store it in the context. |
| 195 int context_offset = Context::SlotOffset(slot->index()); | 195 int context_offset = Context::SlotOffset(slot->index()); |
| 196 __ movq(Operand(rsi, context_offset), rax); | 196 __ movq(Operand(rsi, context_offset), rax); |
| 197 // Update the write barrier. This clobbers all involved | 197 // Update the write barrier. This clobbers rax and rbx. |
|
Vyacheslav Egorov (Chromium)
2011/06/07 14:01:27
rogue space before This
Erik Corry
2011/06/08 10:38:55
It's a fixed width font: http://en.wikipedia.org/
| |
| 198 // registers, so we have use a third register to avoid | 198 __ RecordWriteContextSlot( |
| 199 // clobbering rsi. | 199 rsi, context_offset, rax, rbx, kDontSaveFPRegs); |
| 200 __ movq(rcx, rsi); | |
| 201 __ RecordWrite(rcx, context_offset, rax, rbx, kDontSaveFPRegs); | |
| 202 } | 200 } |
| 203 } | 201 } |
| 204 } | 202 } |
| 205 | 203 |
| 206 // Possibly allocate an arguments object. | 204 // Possibly allocate an arguments object. |
| 207 Variable* arguments = scope()->arguments(); | 205 Variable* arguments = scope()->arguments(); |
| 208 if (arguments != NULL) { | 206 if (arguments != NULL) { |
| 209 // Arguments object must be allocated after the context object, in | 207 // Arguments object must be allocated after the context object, in |
| 210 // case the "arguments" or ".arguments" variables are in the context. | 208 // case the "arguments" or ".arguments" variables are in the context. |
| 211 Comment cmnt(masm_, "[ Allocate arguments object"); | 209 Comment cmnt(masm_, "[ Allocate arguments object"); |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 | 617 |
| 620 | 618 |
| 621 void FullCodeGenerator::Move(Slot* dst, | 619 void FullCodeGenerator::Move(Slot* dst, |
| 622 Register src, | 620 Register src, |
| 623 Register scratch1, | 621 Register scratch1, |
| 624 Register scratch2) { | 622 Register scratch2) { |
| 625 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. | 623 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. |
| 626 ASSERT(!scratch1.is(src) && !scratch2.is(src)); | 624 ASSERT(!scratch1.is(src) && !scratch2.is(src)); |
| 627 MemOperand location = EmitSlotSearch(dst, scratch1); | 625 MemOperand location = EmitSlotSearch(dst, scratch1); |
| 628 __ movq(location, src); | 626 __ movq(location, src); |
| 627 | |
| 629 // Emit the write barrier code if the location is in the heap. | 628 // Emit the write barrier code if the location is in the heap. |
| 630 if (dst->type() == Slot::CONTEXT) { | 629 if (dst->type() == Slot::CONTEXT) { |
| 631 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; | 630 int offset = Context::SlotOffset(dst->index()); |
| 632 __ RecordWrite(scratch1, offset, src, scratch2, kDontSaveFPRegs); | 631 __ RecordWriteContextSlot(scratch1, offset, src, scratch2, kDontSaveFPRegs); |
| 633 } | 632 } |
| 634 } | 633 } |
| 635 | 634 |
| 636 | 635 |
| 637 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, | 636 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, |
| 638 bool should_normalize, | 637 bool should_normalize, |
| 639 Label* if_true, | 638 Label* if_true, |
| 640 Label* if_false) { | 639 Label* if_false) { |
| 641 // Only prepare for bailouts before splits if we're in a test | 640 // Only prepare for bailouts before splits if we're in a test |
| 642 // context. Otherwise, we let the Visit function deal with the | 641 // context. Otherwise, we let the Visit function deal with the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 695 } | 694 } |
| 696 if (mode == Variable::CONST) { | 695 if (mode == Variable::CONST) { |
| 697 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); | 696 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
| 698 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); | 697 __ movq(ContextOperand(rsi, slot->index()), kScratchRegister); |
| 699 // No write barrier since the hole value is in old space. | 698 // No write barrier since the hole value is in old space. |
| 700 } else if (function != NULL) { | 699 } else if (function != NULL) { |
| 701 VisitForAccumulatorValue(function); | 700 VisitForAccumulatorValue(function); |
| 702 __ movq(ContextOperand(rsi, slot->index()), result_register()); | 701 __ movq(ContextOperand(rsi, slot->index()), result_register()); |
| 703 int offset = Context::SlotOffset(slot->index()); | 702 int offset = Context::SlotOffset(slot->index()); |
| 704 // We know that we have written a function, which is not a smi. | 703 // We know that we have written a function, which is not a smi. |
| 705 // TODO(gc): Make sure we omit Smi check here. | 704 __ RecordWriteContextSlot(rsi, |
| 706 __ RecordWrite(rsi, offset, result_register(), rcx, kDontSaveFPRegs); | 705 offset, |
| 706 result_register(), | |
| 707 rcx, | |
| 708 kDontSaveFPRegs, | |
| 709 EMIT_REMEMBERED_SET, | |
| 710 OMIT_SMI_CHECK); | |
| 707 } | 711 } |
| 708 break; | 712 break; |
| 709 | 713 |
| 710 case Slot::LOOKUP: { | 714 case Slot::LOOKUP: { |
| 711 __ push(rsi); | 715 __ push(rsi); |
| 712 __ Push(variable->name()); | 716 __ Push(variable->name()); |
| 713 // Declaration nodes are always introduced in one of two modes. | 717 // Declaration nodes are always introduced in one of two modes. |
| 714 ASSERT(mode == Variable::VAR || mode == Variable::CONST); | 718 ASSERT(mode == Variable::VAR || mode == Variable::CONST); |
| 715 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; | 719 PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY; |
| 716 __ Push(Smi::FromInt(attr)); | 720 __ Push(Smi::FromInt(attr)); |
| (...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1504 } | 1508 } |
| 1505 VisitForAccumulatorValue(subexpr); | 1509 VisitForAccumulatorValue(subexpr); |
| 1506 | 1510 |
| 1507 // Store the subexpression value in the array's elements. | 1511 // Store the subexpression value in the array's elements. |
| 1508 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. | 1512 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. |
| 1509 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); | 1513 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); |
| 1510 int offset = FixedArray::kHeaderSize + (i * kPointerSize); | 1514 int offset = FixedArray::kHeaderSize + (i * kPointerSize); |
| 1511 __ movq(FieldOperand(rbx, offset), result_register()); | 1515 __ movq(FieldOperand(rbx, offset), result_register()); |
| 1512 | 1516 |
| 1513 // Update the write barrier for the array store. | 1517 // Update the write barrier for the array store. |
| 1514 __ RecordWrite(rbx, offset, result_register(), rcx, kDontSaveFPRegs); | 1518 __ RecordWriteField(rbx, offset, result_register(), rcx, kDontSaveFPRegs); |
| 1515 | 1519 |
| 1516 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); | 1520 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); |
| 1517 } | 1521 } |
| 1518 | 1522 |
| 1519 if (result_saved) { | 1523 if (result_saved) { |
| 1520 context()->PlugTOS(); | 1524 context()->PlugTOS(); |
| 1521 } else { | 1525 } else { |
| 1522 context()->Plug(rax); | 1526 context()->Plug(rax); |
| 1523 } | 1527 } |
| 1524 } | 1528 } |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1845 __ movq(Operand(rbp, SlotOffset(slot)), rax); | 1849 __ movq(Operand(rbp, SlotOffset(slot)), rax); |
| 1846 break; | 1850 break; |
| 1847 case Slot::CONTEXT: { | 1851 case Slot::CONTEXT: { |
| 1848 __ movq(rcx, ContextOperand(rsi, Context::FCONTEXT_INDEX)); | 1852 __ movq(rcx, ContextOperand(rsi, Context::FCONTEXT_INDEX)); |
| 1849 __ movq(rdx, ContextOperand(rcx, slot->index())); | 1853 __ movq(rdx, ContextOperand(rcx, slot->index())); |
| 1850 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); | 1854 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); |
| 1851 __ j(not_equal, &skip); | 1855 __ j(not_equal, &skip); |
| 1852 __ movq(ContextOperand(rcx, slot->index()), rax); | 1856 __ movq(ContextOperand(rcx, slot->index()), rax); |
| 1853 int offset = Context::SlotOffset(slot->index()); | 1857 int offset = Context::SlotOffset(slot->index()); |
| 1854 __ movq(rdx, rax); // Preserve the stored value in eax. | 1858 __ movq(rdx, rax); // Preserve the stored value in eax. |
| 1855 __ RecordWrite(rcx, offset, rdx, rbx, kDontSaveFPRegs); | 1859 __ RecordWriteContextSlot(rcx, offset, rdx, rbx, kDontSaveFPRegs); |
| 1856 break; | 1860 break; |
| 1857 } | 1861 } |
| 1858 case Slot::LOOKUP: | 1862 case Slot::LOOKUP: |
| 1859 __ push(rax); | 1863 __ push(rax); |
| 1860 __ push(rsi); | 1864 __ push(rsi); |
| 1861 __ Push(var->name()); | 1865 __ Push(var->name()); |
| 1862 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 1866 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 1863 break; | 1867 break; |
| 1864 } | 1868 } |
| 1865 __ bind(&skip); | 1869 __ bind(&skip); |
| 1866 | 1870 |
| 1867 } else if (var->mode() != Variable::CONST) { | 1871 } else if (var->mode() != Variable::CONST) { |
| 1868 // Perform the assignment for non-const variables. Const assignments | 1872 // Perform the assignment for non-const variables. Const assignments |
| 1869 // are simply skipped. | 1873 // are simply skipped. |
| 1870 Slot* slot = var->AsSlot(); | 1874 Slot* slot = var->AsSlot(); |
| 1871 switch (slot->type()) { | 1875 switch (slot->type()) { |
| 1872 case Slot::PARAMETER: | 1876 case Slot::PARAMETER: |
| 1873 case Slot::LOCAL: | 1877 case Slot::LOCAL: |
| 1874 // Perform the assignment. | 1878 // Perform the assignment. |
| 1875 __ movq(Operand(rbp, SlotOffset(slot)), rax); | 1879 __ movq(Operand(rbp, SlotOffset(slot)), rax); |
| 1876 break; | 1880 break; |
| 1877 | 1881 |
| 1878 case Slot::CONTEXT: { | 1882 case Slot::CONTEXT: { |
| 1879 MemOperand target = EmitSlotSearch(slot, rcx); | 1883 MemOperand target = EmitSlotSearch(slot, rcx); |
| 1880 // Perform the assignment and issue the write barrier. | 1884 // Perform the assignment and issue the write barrier. |
| 1881 __ movq(target, rax); | 1885 __ movq(target, rax); |
| 1882 | 1886 |
| 1883 // The value of the assignment is in rax. RecordWrite clobbers its | 1887 // The value of the assignment is in rax. RecordWrite clobbers its |
| 1884 // register arguments. | 1888 // last two register arguments. |
| 1885 __ movq(rdx, rax); | 1889 __ movq(rdx, rax); |
| 1886 int offset = Context::SlotOffset(slot->index()); | 1890 int offset = Context::SlotOffset(slot->index()); |
| 1887 __ RecordWrite(rcx, offset, rdx, rbx, kDontSaveFPRegs); | 1891 __ RecordWriteContextSlot(rcx, offset, rdx, rbx, kDontSaveFPRegs); |
| 1888 break; | 1892 break; |
| 1889 } | 1893 } |
| 1890 | 1894 |
| 1891 case Slot::LOOKUP: | 1895 case Slot::LOOKUP: |
| 1892 // Call the runtime for the assignment. | 1896 // Call the runtime for the assignment. |
| 1893 __ push(rax); // Value. | 1897 __ push(rax); // Value. |
| 1894 __ push(rsi); // Context. | 1898 __ push(rsi); // Context. |
| 1895 __ Push(var->name()); | 1899 __ Push(var->name()); |
| 1896 __ Push(Smi::FromInt(strict_mode_flag())); | 1900 __ Push(Smi::FromInt(strict_mode_flag())); |
| 1897 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 1901 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| (...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2851 | 2855 |
| 2852 // If the object is not a value type, return the value. | 2856 // If the object is not a value type, return the value. |
| 2853 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); | 2857 __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); |
| 2854 __ j(not_equal, &done); | 2858 __ j(not_equal, &done); |
| 2855 | 2859 |
| 2856 // Store the value. | 2860 // Store the value. |
| 2857 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); | 2861 __ movq(FieldOperand(rbx, JSValue::kValueOffset), rax); |
| 2858 // Update the write barrier. Save the value as it will be | 2862 // Update the write barrier. Save the value as it will be |
| 2859 // overwritten by the write barrier code and is needed afterward. | 2863 // overwritten by the write barrier code and is needed afterward. |
| 2860 __ movq(rdx, rax); | 2864 __ movq(rdx, rax); |
| 2861 __ RecordWrite(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); | 2865 __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); |
| 2862 | 2866 |
| 2863 __ bind(&done); | 2867 __ bind(&done); |
| 2864 context()->Plug(rax); | 2868 context()->Plug(rax); |
| 2865 } | 2869 } |
| 2866 | 2870 |
| 2867 | 2871 |
| 2868 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { | 2872 void FullCodeGenerator::EmitNumberToString(ZoneList<Expression*>* args) { |
| 2869 ASSERT_EQ(args->length(), 1); | 2873 ASSERT_EQ(args->length(), 1); |
| 2870 | 2874 |
| 2871 // Load the argument on the stack and call the stub. | 2875 // Load the argument on the stack and call the stub. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3137 | 3141 |
| 3138 // Swap elements. Use object and temp as scratch registers. | 3142 // Swap elements. Use object and temp as scratch registers. |
| 3139 __ movq(object, Operand(index_1, 0)); | 3143 __ movq(object, Operand(index_1, 0)); |
| 3140 __ movq(temp, Operand(index_2, 0)); | 3144 __ movq(temp, Operand(index_2, 0)); |
| 3141 __ movq(Operand(index_2, 0), object); | 3145 __ movq(Operand(index_2, 0), object); |
| 3142 __ movq(Operand(index_1, 0), temp); | 3146 __ movq(Operand(index_1, 0), temp); |
| 3143 | 3147 |
| 3144 Label new_space; | 3148 Label new_space; |
| 3145 __ InNewSpace(elements, temp, equal, &new_space); | 3149 __ InNewSpace(elements, temp, equal, &new_space); |
| 3146 | 3150 |
| 3147 __ movq(object, elements); | 3151 __ movq(object, elements); |
|
Vyacheslav Egorov (Chromium)
2011/06/07 14:01:27
Is this still required?
Erik Corry
2011/06/08 10:38:55
No, good point.
| |
| 3148 __ RecordWriteHelper(object, index_1, temp, kDontSaveFPRegs); | 3152 __ RememberedSetHelper( |
|
Vyacheslav Egorov (Chromium)
2011/06/07 14:01:27
I think ia32 has a comment that explains why we do
Erik Corry
2011/06/08 10:38:55
Done.
| |
| 3149 __ RecordWriteHelper(elements, index_2, temp, kDontSaveFPRegs); | 3153 index_1, temp, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); |
| 3154 __ RememberedSetHelper( | |
| 3155 index_2, temp, kDontSaveFPRegs, MacroAssembler::kFallThroughAtEnd); | |
| 3150 | 3156 |
| 3151 __ bind(&new_space); | 3157 __ bind(&new_space); |
| 3152 // We are done. Drop elements from the stack, and return undefined. | 3158 // We are done. Drop elements from the stack, and return undefined. |
| 3153 __ addq(rsp, Immediate(3 * kPointerSize)); | 3159 __ addq(rsp, Immediate(3 * kPointerSize)); |
| 3154 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 3160 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
| 3155 __ jmp(&done); | 3161 __ jmp(&done); |
| 3156 | 3162 |
| 3157 __ bind(&slow_case); | 3163 __ bind(&slow_case); |
| 3158 __ CallRuntime(Runtime::kSwapElements, 3); | 3164 __ CallRuntime(Runtime::kSwapElements, 3); |
| 3159 | 3165 |
| (...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4311 __ ret(0); | 4317 __ ret(0); |
| 4312 } | 4318 } |
| 4313 | 4319 |
| 4314 | 4320 |
| 4315 #undef __ | 4321 #undef __ |
| 4316 | 4322 |
| 4317 | 4323 |
| 4318 } } // namespace v8::internal | 4324 } } // namespace v8::internal |
| 4319 | 4325 |
| 4320 #endif // V8_TARGET_ARCH_X64 | 4326 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |