| OLD | NEW | 
|     1 // Copyright 2012 the V8 project authors. All rights reserved. |     1 // Copyright 2012 the V8 project authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #if V8_TARGET_ARCH_X64 |     5 #if V8_TARGET_ARCH_X64 | 
|     6  |     6  | 
|     7 #include "src/ast/scopes.h" |     7 #include "src/ast/scopes.h" | 
|     8 #include "src/code-factory.h" |     8 #include "src/code-factory.h" | 
|     9 #include "src/code-stubs.h" |     9 #include "src/code-stubs.h" | 
|    10 #include "src/codegen.h" |    10 #include "src/codegen.h" | 
| (...skipping 1762 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1773  |  1773  | 
|  1774  |  1774  | 
|  1775 void FullCodeGenerator::VisitYield(Yield* expr) { |  1775 void FullCodeGenerator::VisitYield(Yield* expr) { | 
|  1776   Comment cmnt(masm_, "[ Yield"); |  1776   Comment cmnt(masm_, "[ Yield"); | 
|  1777   SetExpressionPosition(expr); |  1777   SetExpressionPosition(expr); | 
|  1778  |  1778  | 
|  1779   // Evaluate yielded value first; the initial iterator definition depends on |  1779   // Evaluate yielded value first; the initial iterator definition depends on | 
|  1780   // this.  It stays on the stack while we update the iterator. |  1780   // this.  It stays on the stack while we update the iterator. | 
|  1781   VisitForStackValue(expr->expression()); |  1781   VisitForStackValue(expr->expression()); | 
|  1782  |  1782  | 
|  1783   Label suspend, continuation, post_runtime, resume; |  1783   Label suspend, continuation, post_runtime, resume, exception; | 
|  1784  |  1784  | 
|  1785   __ jmp(&suspend); |  1785   __ jmp(&suspend); | 
|  1786   __ bind(&continuation); |  1786   __ bind(&continuation); | 
|  1787   // When we arrive here, the stack top is the resume mode and |  1787   // When we arrive here, the stack top is the resume mode and | 
|  1788   // result_register() holds the input value (the argument given to the |  1788   // result_register() holds the input value (the argument given to the | 
|  1789   // respective resume operation). |  1789   // respective resume operation). | 
|  1790   __ RecordGeneratorContinuation(); |  1790   __ RecordGeneratorContinuation(); | 
|  1791   __ Pop(rbx); |  1791   __ Pop(rbx); | 
|  1792   __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::RETURN)); |  1792   STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); | 
|  1793   __ j(not_equal, &resume); |  1793   STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); | 
 |  1794   __ SmiCompare(rbx, Smi::FromInt(JSGeneratorObject::kReturn)); | 
 |  1795   __ j(less, &resume); | 
|  1794   __ Push(result_register()); |  1796   __ Push(result_register()); | 
 |  1797   __ j(greater, &exception); | 
|  1795   EmitCreateIteratorResult(true); |  1798   EmitCreateIteratorResult(true); | 
|  1796   EmitUnwindAndReturn(); |  1799   EmitUnwindAndReturn(); | 
|  1797  |  1800  | 
 |  1801   __ bind(&exception); | 
 |  1802   __ CallRuntime(Runtime::kThrow); | 
 |  1803  | 
|  1798   __ bind(&suspend); |  1804   __ bind(&suspend); | 
|  1799   OperandStackDepthIncrement(1);  // Not popped on this path. |  1805   OperandStackDepthIncrement(1);  // Not popped on this path. | 
|  1800   VisitForAccumulatorValue(expr->generator_object()); |  1806   VisitForAccumulatorValue(expr->generator_object()); | 
|  1801   DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |  1807   DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 
|  1802   __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), |  1808   __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), | 
|  1803           Smi::FromInt(continuation.pos())); |  1809           Smi::FromInt(continuation.pos())); | 
|  1804   __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); |  1810   __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); | 
|  1805   __ movp(rcx, rsi); |  1811   __ movp(rcx, rsi); | 
|  1806   __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, |  1812   __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, | 
|  1807                       kDontSaveFPRegs); |  1813                       kDontSaveFPRegs); | 
|  1808   __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); |  1814   __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); | 
|  1809   __ cmpp(rsp, rbx); |  1815   __ cmpp(rsp, rbx); | 
|  1810   __ j(equal, &post_runtime); |  1816   __ j(equal, &post_runtime); | 
|  1811   __ Push(rax);  // generator object |  1817   __ Push(rax);  // generator object | 
|  1812   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |  1818   __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 
|  1813   __ movp(context_register(), |  1819   __ movp(context_register(), | 
|  1814           Operand(rbp, StandardFrameConstants::kContextOffset)); |  1820           Operand(rbp, StandardFrameConstants::kContextOffset)); | 
|  1815   __ bind(&post_runtime); |  1821   __ bind(&post_runtime); | 
|  1816  |  1822  | 
|  1817   PopOperand(result_register()); |  1823   PopOperand(result_register()); | 
|  1818   EmitReturnSequence(); |  1824   EmitReturnSequence(); | 
|  1819  |  1825  | 
|  1820   __ bind(&resume); |  1826   __ bind(&resume); | 
|  1821   context()->Plug(result_register()); |  1827   context()->Plug(result_register()); | 
|  1822 } |  1828 } | 
|  1823  |  1829  | 
|  1824  |  | 
|  1825 void FullCodeGenerator::EmitGeneratorResume( |  | 
|  1826     Expression* generator, Expression* value, |  | 
|  1827     JSGeneratorObject::ResumeMode resume_mode) { |  | 
|  1828   // The value stays in rax, and is ultimately read by the resumed generator, as |  | 
|  1829   // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |  | 
|  1830   // is read to throw the value when the resumed generator is already closed. |  | 
|  1831   // rbx will hold the generator object until the activation has been resumed. |  | 
|  1832   VisitForStackValue(generator); |  | 
|  1833   VisitForAccumulatorValue(value); |  | 
|  1834   PopOperand(rbx); |  | 
|  1835  |  | 
|  1836   // Store input value into generator object. |  | 
|  1837   __ movp(FieldOperand(rbx, JSGeneratorObject::kInputOffset), |  | 
|  1838           result_register()); |  | 
|  1839   __ movp(rcx, result_register()); |  | 
|  1840   __ RecordWriteField(rbx, JSGeneratorObject::kInputOffset, rcx, rdx, |  | 
|  1841                       kDontSaveFPRegs); |  | 
|  1842  |  | 
|  1843   // Load suspended function and context. |  | 
|  1844   __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset)); |  | 
|  1845   __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset)); |  | 
|  1846  |  | 
|  1847   // Push receiver. |  | 
|  1848   __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset)); |  | 
|  1849  |  | 
|  1850   // Push holes for arguments to generator function. Since the parser forced |  | 
|  1851   // context allocation for any variables in generators, the actual argument |  | 
|  1852   // values have already been copied into the context and these dummy values |  | 
|  1853   // will never be used. |  | 
|  1854   __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |  | 
|  1855   __ LoadSharedFunctionInfoSpecialField(rdx, rdx, |  | 
|  1856       SharedFunctionInfo::kFormalParameterCountOffset); |  | 
|  1857   __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex); |  | 
|  1858   Label push_argument_holes, push_frame; |  | 
|  1859   __ bind(&push_argument_holes); |  | 
|  1860   __ subp(rdx, Immediate(1)); |  | 
|  1861   __ j(carry, &push_frame); |  | 
|  1862   __ Push(rcx); |  | 
|  1863   __ jmp(&push_argument_holes); |  | 
|  1864  |  | 
|  1865   // Enter a new JavaScript frame, and initialize its slots as they were when |  | 
|  1866   // the generator was suspended. |  | 
|  1867   Label resume_frame, done; |  | 
|  1868   __ bind(&push_frame); |  | 
|  1869   __ call(&resume_frame); |  | 
|  1870   __ jmp(&done); |  | 
|  1871   __ bind(&resume_frame); |  | 
|  1872   __ pushq(rbp);  // Caller's frame pointer. |  | 
|  1873   __ movp(rbp, rsp); |  | 
|  1874   __ Push(rsi);  // Callee's context. |  | 
|  1875   __ Push(rdi);  // Callee's JS Function. |  | 
|  1876  |  | 
|  1877   // Load the operand stack size. |  | 
|  1878   __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset)); |  | 
|  1879   __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset)); |  | 
|  1880   __ SmiToInteger32(rdx, rdx); |  | 
|  1881  |  | 
|  1882   // If we are sending a value and there is no operand stack, we can jump back |  | 
|  1883   // in directly. |  | 
|  1884   if (resume_mode == JSGeneratorObject::NEXT) { |  | 
|  1885     Label slow_resume; |  | 
|  1886     __ cmpp(rdx, Immediate(0)); |  | 
|  1887     __ j(not_zero, &slow_resume); |  | 
|  1888     __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |  | 
|  1889     __ SmiToInteger64(rcx, |  | 
|  1890         FieldOperand(rbx, JSGeneratorObject::kContinuationOffset)); |  | 
|  1891     __ addp(rdx, rcx); |  | 
|  1892     __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), |  | 
|  1893             Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)); |  | 
|  1894     __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation. |  | 
|  1895     __ jmp(rdx); |  | 
|  1896     __ bind(&slow_resume); |  | 
|  1897   } |  | 
|  1898  |  | 
|  1899   // Otherwise, we push holes for the operand stack and call the runtime to fix |  | 
|  1900   // up the stack and the handlers. |  | 
|  1901   Label push_operand_holes, call_resume; |  | 
|  1902   __ bind(&push_operand_holes); |  | 
|  1903   __ subp(rdx, Immediate(1)); |  | 
|  1904   __ j(carry, &call_resume); |  | 
|  1905   __ Push(rcx); |  | 
|  1906   __ jmp(&push_operand_holes); |  | 
|  1907   __ bind(&call_resume); |  | 
|  1908   __ Push(Smi::FromInt(resume_mode));  // Consumed in continuation. |  | 
|  1909   __ Push(rbx); |  | 
|  1910   __ Push(result_register()); |  | 
|  1911   __ Push(Smi::FromInt(resume_mode)); |  | 
|  1912   __ CallRuntime(Runtime::kResumeJSGeneratorObject); |  | 
|  1913   // Not reached: the runtime call returns elsewhere. |  | 
|  1914   __ Abort(kGeneratorFailedToResume); |  | 
|  1915  |  | 
|  1916   __ bind(&done); |  | 
|  1917   context()->Plug(result_register()); |  | 
|  1918 } |  | 
|  1919  |  | 
|  1920 void FullCodeGenerator::PushOperand(MemOperand operand) { |  1830 void FullCodeGenerator::PushOperand(MemOperand operand) { | 
|  1921   OperandStackDepthIncrement(1); |  1831   OperandStackDepthIncrement(1); | 
|  1922   __ Push(operand); |  1832   __ Push(operand); | 
|  1923 } |  1833 } | 
|  1924  |  1834  | 
|  1925 void FullCodeGenerator::EmitOperandStackDepthCheck() { |  1835 void FullCodeGenerator::EmitOperandStackDepthCheck() { | 
|  1926   if (FLAG_debug_code) { |  1836   if (FLAG_debug_code) { | 
|  1927     int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + |  1837     int expected_diff = StandardFrameConstants::kFixedFrameSizeFromFp + | 
|  1928                         operand_stack_depth_ * kPointerSize; |  1838                         operand_stack_depth_ * kPointerSize; | 
|  1929     __ movp(rax, rbp); |  1839     __ movp(rax, rbp); | 
| (...skipping 2040 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3970   DCHECK_EQ( |  3880   DCHECK_EQ( | 
|  3971       isolate->builtins()->OnStackReplacement()->entry(), |  3881       isolate->builtins()->OnStackReplacement()->entry(), | 
|  3972       Assembler::target_address_at(call_target_address, unoptimized_code)); |  3882       Assembler::target_address_at(call_target_address, unoptimized_code)); | 
|  3973   return ON_STACK_REPLACEMENT; |  3883   return ON_STACK_REPLACEMENT; | 
|  3974 } |  3884 } | 
|  3975  |  3885  | 
|  3976 }  // namespace internal |  3886 }  // namespace internal | 
|  3977 }  // namespace v8 |  3887 }  // namespace v8 | 
|  3978  |  3888  | 
|  3979 #endif  // V8_TARGET_ARCH_X64 |  3889 #endif  // V8_TARGET_ARCH_X64 | 
| OLD | NEW |