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_ARM | 5 #if V8_TARGET_ARCH_ARM |
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 1822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 | 1833 |
1834 | 1834 |
1835 void FullCodeGenerator::VisitYield(Yield* expr) { | 1835 void FullCodeGenerator::VisitYield(Yield* expr) { |
1836 Comment cmnt(masm_, "[ Yield"); | 1836 Comment cmnt(masm_, "[ Yield"); |
1837 SetExpressionPosition(expr); | 1837 SetExpressionPosition(expr); |
1838 | 1838 |
1839 // Evaluate yielded value first; the initial iterator definition depends on | 1839 // Evaluate yielded value first; the initial iterator definition depends on |
1840 // this. It stays on the stack while we update the iterator. | 1840 // this. It stays on the stack while we update the iterator. |
1841 VisitForStackValue(expr->expression()); | 1841 VisitForStackValue(expr->expression()); |
1842 | 1842 |
1843 Label suspend, continuation, post_runtime, resume; | 1843 Label suspend, continuation, post_runtime, resume, exception; |
1844 | 1844 |
1845 __ jmp(&suspend); | 1845 __ jmp(&suspend); |
1846 __ bind(&continuation); | 1846 __ bind(&continuation); |
1847 // When we arrive here, the stack top is the resume mode and | 1847 // When we arrive here, the stack top is the resume mode and |
1848 // result_register() holds the input value (the argument given to the | 1848 // result_register() holds the input value (the argument given to the |
1849 // respective resume operation). | 1849 // respective resume operation). |
1850 __ RecordGeneratorContinuation(); | 1850 __ RecordGeneratorContinuation(); |
1851 __ pop(r1); | 1851 __ pop(r1); |
1852 __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::RETURN))); | 1852 STATIC_ASSERT(JSGeneratorObject::kNext < JSGeneratorObject::kReturn); |
1853 __ b(ne, &resume); | 1853 STATIC_ASSERT(JSGeneratorObject::kThrow > JSGeneratorObject::kReturn); |
1854 __ push(result_register()); | 1854 __ cmp(r1, Operand(Smi::FromInt(JSGeneratorObject::kReturn))); |
| 1855 __ b(lt, &resume); |
| 1856 __ Push(result_register()); |
| 1857 __ b(gt, &exception); |
1855 EmitCreateIteratorResult(true); | 1858 EmitCreateIteratorResult(true); |
1856 EmitUnwindAndReturn(); | 1859 EmitUnwindAndReturn(); |
1857 | 1860 |
| 1861 __ bind(&exception); |
| 1862 __ CallRuntime(Runtime::kThrow); |
| 1863 |
1858 __ bind(&suspend); | 1864 __ bind(&suspend); |
1859 OperandStackDepthIncrement(1); // Not popped on this path. | 1865 OperandStackDepthIncrement(1); // Not popped on this path. |
1860 VisitForAccumulatorValue(expr->generator_object()); | 1866 VisitForAccumulatorValue(expr->generator_object()); |
1861 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1867 DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
1862 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); | 1868 __ mov(r1, Operand(Smi::FromInt(continuation.pos()))); |
1863 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); | 1869 __ str(r1, FieldMemOperand(r0, JSGeneratorObject::kContinuationOffset)); |
1864 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); | 1870 __ str(cp, FieldMemOperand(r0, JSGeneratorObject::kContextOffset)); |
1865 __ mov(r1, cp); | 1871 __ mov(r1, cp); |
1866 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, | 1872 __ RecordWriteField(r0, JSGeneratorObject::kContextOffset, r1, r2, |
1867 kLRHasBeenSaved, kDontSaveFPRegs); | 1873 kLRHasBeenSaved, kDontSaveFPRegs); |
1868 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); | 1874 __ add(r1, fp, Operand(StandardFrameConstants::kExpressionsOffset)); |
1869 __ cmp(sp, r1); | 1875 __ cmp(sp, r1); |
1870 __ b(eq, &post_runtime); | 1876 __ b(eq, &post_runtime); |
1871 __ push(r0); // generator object | 1877 __ push(r0); // generator object |
1872 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1878 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1873 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1879 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
1874 __ bind(&post_runtime); | 1880 __ bind(&post_runtime); |
1875 PopOperand(result_register()); | 1881 PopOperand(result_register()); |
1876 EmitReturnSequence(); | 1882 EmitReturnSequence(); |
1877 | 1883 |
1878 __ bind(&resume); | 1884 __ bind(&resume); |
1879 context()->Plug(result_register()); | 1885 context()->Plug(result_register()); |
1880 } | 1886 } |
1881 | 1887 |
1882 | |
1883 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, | |
1884 Expression *value, | |
1885 JSGeneratorObject::ResumeMode resume_mode) { | |
1886 // The value stays in r0, and is ultimately read by the resumed generator, as | |
1887 // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | |
1888 // is read to throw the value when the resumed generator is already closed. | |
1889 // r1 will hold the generator object until the activation has been resumed. | |
1890 VisitForStackValue(generator); | |
1891 VisitForAccumulatorValue(value); | |
1892 PopOperand(r1); | |
1893 | |
1894 // Store input value into generator object. | |
1895 __ str(result_register(), | |
1896 FieldMemOperand(r1, JSGeneratorObject::kInputOffset)); | |
1897 __ mov(r2, result_register()); | |
1898 __ RecordWriteField(r1, JSGeneratorObject::kInputOffset, r2, r3, | |
1899 kLRHasBeenSaved, kDontSaveFPRegs); | |
1900 | |
1901 // Load suspended function and context. | |
1902 __ ldr(cp, FieldMemOperand(r1, JSGeneratorObject::kContextOffset)); | |
1903 __ ldr(r4, FieldMemOperand(r1, JSGeneratorObject::kFunctionOffset)); | |
1904 | |
1905 // Load receiver and store as the first argument. | |
1906 __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kReceiverOffset)); | |
1907 __ push(r2); | |
1908 | |
1909 // Push holes for arguments to generator function. Since the parser forced | |
1910 // context allocation for any variables in generators, the actual argument | |
1911 // values have already been copied into the context and these dummy values | |
1912 // will never be used. | |
1913 __ ldr(r3, FieldMemOperand(r4, JSFunction::kSharedFunctionInfoOffset)); | |
1914 __ ldr(r3, | |
1915 FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); | |
1916 __ LoadRoot(r2, Heap::kTheHoleValueRootIndex); | |
1917 Label push_argument_holes, push_frame; | |
1918 __ bind(&push_argument_holes); | |
1919 __ sub(r3, r3, Operand(Smi::FromInt(1)), SetCC); | |
1920 __ b(mi, &push_frame); | |
1921 __ push(r2); | |
1922 __ jmp(&push_argument_holes); | |
1923 | |
1924 // Enter a new JavaScript frame, and initialize its slots as they were when | |
1925 // the generator was suspended. | |
1926 Label resume_frame, done; | |
1927 __ bind(&push_frame); | |
1928 __ bl(&resume_frame); | |
1929 __ jmp(&done); | |
1930 __ bind(&resume_frame); | |
1931 // lr = return address. | |
1932 // fp = caller's frame pointer. | |
1933 // pp = caller's constant pool (if FLAG_enable_embedded_constant_pool), | |
1934 // cp = callee's context, | |
1935 // r4 = callee's JS function. | |
1936 __ PushStandardFrame(r4); | |
1937 | |
1938 // Load the operand stack size. | |
1939 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); | |
1940 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); | |
1941 __ SmiUntag(r3); | |
1942 | |
1943 // If we are sending a value and there is no operand stack, we can jump back | |
1944 // in directly. | |
1945 if (resume_mode == JSGeneratorObject::NEXT) { | |
1946 Label slow_resume; | |
1947 __ cmp(r3, Operand(0)); | |
1948 __ b(ne, &slow_resume); | |
1949 __ ldr(r3, FieldMemOperand(r4, JSFunction::kCodeEntryOffset)); | |
1950 | |
1951 { ConstantPoolUnavailableScope constant_pool_unavailable(masm_); | |
1952 if (FLAG_enable_embedded_constant_pool) { | |
1953 // Load the new code object's constant pool pointer. | |
1954 __ LoadConstantPoolPointerRegisterFromCodeTargetAddress(r3); | |
1955 } | |
1956 | |
1957 __ ldr(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); | |
1958 __ SmiUntag(r2); | |
1959 __ add(r3, r3, r2); | |
1960 __ mov(r2, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))); | |
1961 __ str(r2, FieldMemOperand(r1, JSGeneratorObject::kContinuationOffset)); | |
1962 __ Push(Smi::FromInt(resume_mode)); // Consumed in continuation. | |
1963 __ Jump(r3); | |
1964 } | |
1965 __ bind(&slow_resume); | |
1966 } | |
1967 | |
1968 // Otherwise, we push holes for the operand stack and call the runtime to fix | |
1969 // up the stack and the handlers. | |
1970 Label push_operand_holes, call_resume; | |
1971 __ bind(&push_operand_holes); | |
1972 __ sub(r3, r3, Operand(1), SetCC); | |
1973 __ b(mi, &call_resume); | |
1974 __ push(r2); | |
1975 __ b(&push_operand_holes); | |
1976 __ bind(&call_resume); | |
1977 __ Push(Smi::FromInt(resume_mode)); // Consumed in continuation. | |
1978 DCHECK(!result_register().is(r1)); | |
1979 __ Push(r1, result_register()); | |
1980 __ Push(Smi::FromInt(resume_mode)); | |
1981 __ CallRuntime(Runtime::kResumeJSGeneratorObject); | |
1982 // Not reached: the runtime call returns elsewhere. | |
1983 __ stop("not-reached"); | |
1984 | |
1985 __ bind(&done); | |
1986 context()->Plug(result_register()); | |
1987 } | |
1988 | |
1989 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { | 1888 void FullCodeGenerator::PushOperands(Register reg1, Register reg2) { |
1990 OperandStackDepthIncrement(2); | 1889 OperandStackDepthIncrement(2); |
1991 __ Push(reg1, reg2); | 1890 __ Push(reg1, reg2); |
1992 } | 1891 } |
1993 | 1892 |
1994 void FullCodeGenerator::PopOperands(Register reg1, Register reg2) { | 1893 void FullCodeGenerator::PopOperands(Register reg1, Register reg2) { |
1995 OperandStackDepthDecrement(2); | 1894 OperandStackDepthDecrement(2); |
1996 __ Pop(reg1, reg2); | 1895 __ Pop(reg1, reg2); |
1997 } | 1896 } |
1998 | 1897 |
(...skipping 2157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4156 DCHECK(interrupt_address == | 4055 DCHECK(interrupt_address == |
4157 isolate->builtins()->OnStackReplacement()->entry()); | 4056 isolate->builtins()->OnStackReplacement()->entry()); |
4158 return ON_STACK_REPLACEMENT; | 4057 return ON_STACK_REPLACEMENT; |
4159 } | 4058 } |
4160 | 4059 |
4161 | 4060 |
4162 } // namespace internal | 4061 } // namespace internal |
4163 } // namespace v8 | 4062 } // namespace v8 |
4164 | 4063 |
4165 #endif // V8_TARGET_ARCH_ARM | 4064 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |