Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1943 __ jmp(&suspend); | 1943 __ jmp(&suspend); |
| 1944 | 1944 |
| 1945 __ bind(&continuation); | 1945 __ bind(&continuation); |
| 1946 __ jmp(&resume); | 1946 __ jmp(&resume); |
| 1947 | 1947 |
| 1948 __ bind(&suspend); | 1948 __ bind(&suspend); |
| 1949 VisitForAccumulatorValue(expr->generator_object()); | 1949 VisitForAccumulatorValue(expr->generator_object()); |
| 1950 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); | 1950 ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); |
| 1951 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), | 1951 __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset), |
| 1952 Immediate(Smi::FromInt(continuation.pos()))); | 1952 Immediate(Smi::FromInt(continuation.pos()))); |
| 1953 if (expr->yield_kind() == Yield::INITIAL) { | |
| 1954 __ mov(FieldOperand(eax, JSGeneratorObject::kSuspendedStartOffset), | |
| 1955 Immediate(Smi::FromInt(continuation.pos()))); | |
| 1956 } | |
| 1953 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); | 1957 __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi); |
| 1954 __ mov(ecx, esi); | 1958 __ mov(ecx, esi); |
| 1955 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, | 1959 __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx, |
| 1956 kDontSaveFPRegs); | 1960 kDontSaveFPRegs); |
| 1957 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); | 1961 __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset)); |
| 1958 __ cmp(esp, ebx); | 1962 __ cmp(esp, ebx); |
| 1959 __ j(equal, &post_runtime); | 1963 __ j(equal, &post_runtime); |
| 1960 __ push(eax); // generator object | 1964 __ push(eax); // generator object |
| 1961 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1965 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
| 1962 __ mov(context_register(), | 1966 __ mov(context_register(), |
| 1963 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1967 Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 1964 __ bind(&post_runtime); | 1968 __ bind(&post_runtime); |
| 1965 __ pop(result_register()); | 1969 __ pop(result_register()); |
| 1966 EmitReturnSequence(); | 1970 EmitReturnSequence(); |
| 1967 | 1971 |
| 1968 __ bind(&resume); | 1972 __ bind(&resume); |
|
wingo
2014/02/11 08:59:21
Instead of storing the initial suspend offset in t
yusukesuzuki
2014/02/11 11:46:59
Yeah, saving a word in each generator object is im
| |
| 1969 context()->Plug(result_register()); | 1973 context()->Plug(result_register()); |
| 1970 break; | 1974 break; |
| 1971 } | 1975 } |
| 1972 | 1976 |
| 1973 case Yield::FINAL: { | 1977 case Yield::FINAL: { |
| 1974 VisitForAccumulatorValue(expr->generator_object()); | 1978 VisitForAccumulatorValue(expr->generator_object()); |
| 1975 __ mov(FieldOperand(result_register(), | 1979 __ mov(FieldOperand(result_register(), |
| 1976 JSGeneratorObject::kContinuationOffset), | 1980 JSGeneratorObject::kContinuationOffset), |
| 1977 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); | 1981 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); |
| 1978 // Pop value from top-of-stack slot, box result into result register. | 1982 // Pop value from top-of-stack slot, box result into result register. |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2075 JSGeneratorObject::ResumeMode resume_mode) { | 2079 JSGeneratorObject::ResumeMode resume_mode) { |
| 2076 // The value stays in eax, and is ultimately read by the resumed generator, as | 2080 // The value stays in eax, and is ultimately read by the resumed generator, as |
| 2077 // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it | 2081 // if the CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it |
| 2078 // is read to throw the value when the resumed generator is already closed. | 2082 // is read to throw the value when the resumed generator is already closed. |
| 2079 // ebx will hold the generator object until the activation has been resumed. | 2083 // ebx will hold the generator object until the activation has been resumed. |
| 2080 VisitForStackValue(generator); | 2084 VisitForStackValue(generator); |
| 2081 VisitForAccumulatorValue(value); | 2085 VisitForAccumulatorValue(value); |
| 2082 __ pop(ebx); | 2086 __ pop(ebx); |
| 2083 | 2087 |
| 2084 // Check generator state. | 2088 // Check generator state. |
| 2085 Label wrong_state, closed_state, done; | 2089 Label wrong_state, closed_state, suspended_start_state, resume_state, done; |
| 2086 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); | 2090 STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); |
| 2087 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); | 2091 STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); |
| 2088 __ cmp(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset), | 2092 __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContinuationOffset)); |
| 2089 Immediate(Smi::FromInt(0))); | 2093 __ cmp(esi, Immediate(Smi::FromInt(0))); |
| 2090 __ j(equal, &closed_state); | 2094 __ j(equal, &closed_state); |
| 2091 __ j(less, &wrong_state); | 2095 __ j(less, &wrong_state); |
| 2096 __ cmp(esi, FieldOperand(ebx, JSGeneratorObject::kSuspendedStartOffset)); | |
| 2097 __ j(equal, &suspended_start_state); | |
| 2098 | |
| 2099 __ bind(&resume_state); | |
| 2092 | 2100 |
| 2093 // Load suspended function and context. | 2101 // Load suspended function and context. |
| 2094 __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); | 2102 __ mov(esi, FieldOperand(ebx, JSGeneratorObject::kContextOffset)); |
| 2095 __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); | 2103 __ mov(edi, FieldOperand(ebx, JSGeneratorObject::kFunctionOffset)); |
| 2096 | 2104 |
| 2097 // Push receiver. | 2105 // Push receiver. |
| 2098 __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset)); | 2106 __ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset)); |
| 2099 | 2107 |
| 2100 // Push holes for arguments to generator function. | 2108 // Push holes for arguments to generator function. |
| 2101 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2109 __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2151 __ push(ecx); | 2159 __ push(ecx); |
| 2152 __ jmp(&push_operand_holes); | 2160 __ jmp(&push_operand_holes); |
| 2153 __ bind(&call_resume); | 2161 __ bind(&call_resume); |
| 2154 __ push(ebx); | 2162 __ push(ebx); |
| 2155 __ push(result_register()); | 2163 __ push(result_register()); |
| 2156 __ Push(Smi::FromInt(resume_mode)); | 2164 __ Push(Smi::FromInt(resume_mode)); |
| 2157 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2165 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2158 // Not reached: the runtime call returns elsewhere. | 2166 // Not reached: the runtime call returns elsewhere. |
| 2159 __ Abort(kGeneratorFailedToResume); | 2167 __ Abort(kGeneratorFailedToResume); |
| 2160 | 2168 |
| 2169 // Throw the provided value. | |
| 2170 Label throw_provided_value; | |
| 2171 __ bind(&throw_provided_value); | |
| 2172 if (resume_mode != JSGeneratorObject::NEXT) { | |
| 2173 __ push(eax); | |
| 2174 __ CallRuntime(Runtime::kThrow, 1); | |
| 2175 __ jmp(&done); | |
| 2176 } | |
| 2177 | |
| 2178 // Reach here when calling initial resume to a generator. | |
| 2179 __ bind(&suspended_start_state); | |
| 2180 if (resume_mode == JSGeneratorObject::NEXT) { | |
| 2181 // When value is provided and it is not undefined, throw error. | |
| 2182 __ CompareRoot(eax, Heap::kUndefinedValueRootIndex); | |
| 2183 __ j(equal, &resume_state); | |
| 2184 __ CallRuntime(Runtime::kThrowGeneratorStartError, 0); | |
| 2185 __ jmp(&done); | |
| 2186 } else { | |
| 2187 // Make generator's state to "closed". | |
| 2188 __ mov(FieldOperand(ebx, JSGeneratorObject::kContinuationOffset), | |
| 2189 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); | |
| 2190 __ jmp(&throw_provided_value); | |
| 2191 } | |
| 2192 | |
| 2161 // Reach here when generator is closed. | 2193 // Reach here when generator is closed. |
| 2162 __ bind(&closed_state); | 2194 __ bind(&closed_state); |
| 2163 if (resume_mode == JSGeneratorObject::NEXT) { | 2195 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2164 // Return completed iterator result when generator is closed. | 2196 // Return completed iterator result when generator is closed. |
| 2165 __ push(Immediate(isolate()->factory()->undefined_value())); | 2197 __ push(Immediate(isolate()->factory()->undefined_value())); |
| 2166 // Pop value from top-of-stack slot; box result into result register. | 2198 // Pop value from top-of-stack slot; box result into result register. |
| 2167 EmitCreateIteratorResult(true); | 2199 EmitCreateIteratorResult(true); |
| 2200 __ jmp(&done); | |
| 2168 } else { | 2201 } else { |
| 2169 // Throw the provided value. | 2202 __ jmp(&throw_provided_value); |
| 2170 __ push(eax); | |
| 2171 __ CallRuntime(Runtime::kThrow, 1); | |
| 2172 } | 2203 } |
| 2173 __ jmp(&done); | |
| 2174 | 2204 |
| 2175 // Throw error if we attempt to operate on a running generator. | 2205 // Throw error if we attempt to operate on a running generator. |
| 2176 __ bind(&wrong_state); | 2206 __ bind(&wrong_state); |
| 2177 __ push(ebx); | 2207 __ push(ebx); |
| 2178 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2208 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2179 | 2209 |
| 2180 __ bind(&done); | 2210 __ bind(&done); |
| 2181 context()->Plug(result_register()); | 2211 context()->Plug(result_register()); |
| 2182 } | 2212 } |
| 2183 | 2213 |
| (...skipping 2714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4898 | 4928 |
| 4899 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), | 4929 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), |
| 4900 Assembler::target_address_at(call_target_address)); | 4930 Assembler::target_address_at(call_target_address)); |
| 4901 return OSR_AFTER_STACK_CHECK; | 4931 return OSR_AFTER_STACK_CHECK; |
| 4902 } | 4932 } |
| 4903 | 4933 |
| 4904 | 4934 |
| 4905 } } // namespace v8::internal | 4935 } } // namespace v8::internal |
| 4906 | 4936 |
| 4907 #endif // V8_TARGET_ARCH_IA32 | 4937 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |