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 } | 1943 } |
1944 | 1944 |
1945 | 1945 |
1946 void FullCodeGenerator::VisitYield(Yield* expr) { | 1946 void FullCodeGenerator::VisitYield(Yield* expr) { |
1947 Comment cmnt(masm_, "[ Yield"); | 1947 Comment cmnt(masm_, "[ Yield"); |
1948 // Evaluate yielded value first; the initial iterator definition depends on | 1948 // Evaluate yielded value first; the initial iterator definition depends on |
1949 // this. It stays on the stack while we update the iterator. | 1949 // this. It stays on the stack while we update the iterator. |
1950 VisitForStackValue(expr->expression()); | 1950 VisitForStackValue(expr->expression()); |
1951 | 1951 |
1952 switch (expr->yield_kind()) { | 1952 switch (expr->yield_kind()) { |
1953 case Yield::INITIAL: | 1953 case Yield::SUSPEND: |
1954 case Yield::SUSPEND: { | 1954 // Pop value from top-of-stack slot; box result into result register. |
| 1955 EmitCreateIteratorResult(false); |
| 1956 __ push(result_register()); |
| 1957 // Fall through. |
| 1958 case Yield::INITIAL: { |
1955 VisitForStackValue(expr->generator_object()); | 1959 VisitForStackValue(expr->generator_object()); |
1956 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 1960 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
1957 __ mov(context_register(), | 1961 __ mov(context_register(), |
1958 Operand(ebp, StandardFrameConstants::kContextOffset)); | 1962 Operand(ebp, StandardFrameConstants::kContextOffset)); |
1959 | 1963 |
1960 Label resume; | 1964 Label resume; |
1961 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); | 1965 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); |
1962 __ j(not_equal, &resume); | 1966 __ j(not_equal, &resume); |
1963 if (expr->yield_kind() == Yield::SUSPEND) { | 1967 __ pop(result_register()); |
1964 EmitReturnIteratorResult(false); | 1968 EmitReturnSequence(); |
1965 } else { | |
1966 __ pop(result_register()); | |
1967 EmitReturnSequence(); | |
1968 } | |
1969 | 1969 |
1970 __ bind(&resume); | 1970 __ bind(&resume); |
1971 context()->Plug(result_register()); | 1971 context()->Plug(result_register()); |
1972 break; | 1972 break; |
1973 } | 1973 } |
1974 | 1974 |
1975 case Yield::FINAL: { | 1975 case Yield::FINAL: { |
1976 VisitForAccumulatorValue(expr->generator_object()); | 1976 VisitForAccumulatorValue(expr->generator_object()); |
1977 __ mov(FieldOperand(result_register(), | 1977 __ mov(FieldOperand(result_register(), |
1978 JSGeneratorObject::kContinuationOffset), | 1978 JSGeneratorObject::kContinuationOffset), |
1979 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); | 1979 Immediate(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); |
1980 EmitReturnIteratorResult(true); | 1980 // Pop value from top-of-stack slot, box result into result register. |
| 1981 EmitCreateIteratorResult(true); |
| 1982 EmitUnwindBeforeReturn(); |
| 1983 EmitReturnSequence(); |
1981 break; | 1984 break; |
1982 } | 1985 } |
1983 | 1986 |
1984 case Yield::DELEGATING: { | 1987 case Yield::DELEGATING: { |
1985 VisitForStackValue(expr->generator_object()); | 1988 VisitForStackValue(expr->generator_object()); |
1986 | 1989 |
1987 // Initial stack layout is as follows: | 1990 // Initial stack layout is as follows: |
1988 // [sp + 1 * kPointerSize] iter | 1991 // [sp + 1 * kPointerSize] iter |
1989 // [sp + 0 * kPointerSize] g | 1992 // [sp + 0 * kPointerSize] g |
1990 | 1993 |
1991 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; | 1994 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; |
1992 // Initial send value is undefined. | 1995 // Initial send value is undefined. |
1993 __ mov(eax, isolate()->factory()->undefined_value()); | 1996 __ mov(eax, isolate()->factory()->undefined_value()); |
1994 __ jmp(&l_next); | 1997 __ jmp(&l_next); |
1995 | 1998 |
1996 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } | 1999 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } |
1997 __ bind(&l_catch); | 2000 __ bind(&l_catch); |
1998 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2001 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
1999 __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter | 2002 __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter |
2000 __ push(edx); // iter | 2003 __ push(edx); // iter |
2001 __ push(eax); // exception | 2004 __ push(eax); // exception |
2002 __ mov(ecx, isolate()->factory()->throw_string()); // "throw" | 2005 __ mov(ecx, isolate()->factory()->throw_string()); // "throw" |
2003 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); | 2006 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); |
2004 CallIC(throw_ic); // iter.throw in eax | 2007 CallIC(throw_ic); // iter.throw in eax |
2005 __ jmp(&l_call); | 2008 __ jmp(&l_call); |
2006 | 2009 |
2007 // try { received = yield result.value } | 2010 // try { received = yield result.value } |
2008 __ bind(&l_try); | 2011 __ bind(&l_try); |
2009 __ pop(eax); // result.value | 2012 EmitCreateIteratorResult(false); // pop and box to eax |
2010 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2013 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2011 const int handler_size = StackHandlerConstants::kSize; | 2014 const int handler_size = StackHandlerConstants::kSize; |
2012 __ push(eax); // result.value | 2015 __ push(eax); // result |
2013 __ push(Operand(esp, (0 + 1) * kPointerSize + handler_size)); // g | 2016 __ push(Operand(esp, (0 + 1) * kPointerSize + handler_size)); // g |
2014 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2017 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2015 __ mov(context_register(), | 2018 __ mov(context_register(), |
2016 Operand(ebp, StandardFrameConstants::kContextOffset)); | 2019 Operand(ebp, StandardFrameConstants::kContextOffset)); |
2017 __ CompareRoot(eax, Heap::kTheHoleValueRootIndex); | 2020 __ CompareRoot(eax, Heap::kTheHoleValueRootIndex); |
2018 __ j(not_equal, &l_resume); | 2021 __ j(not_equal, &l_resume); |
2019 EmitReturnIteratorResult(false); | 2022 __ pop(eax); // result |
| 2023 EmitReturnSequence(); |
2020 __ bind(&l_resume); // received in eax | 2024 __ bind(&l_resume); // received in eax |
2021 __ PopTryHandler(); | 2025 __ PopTryHandler(); |
2022 | 2026 |
2023 // receiver = iter; f = iter.next; arg = received; | 2027 // receiver = iter; f = iter.next; arg = received; |
2024 __ bind(&l_next); | 2028 __ bind(&l_next); |
2025 __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter | 2029 __ mov(edx, Operand(esp, 1 * kPointerSize)); // iter |
2026 __ push(edx); // iter | 2030 __ push(edx); // iter |
2027 __ push(eax); // received | 2031 __ push(eax); // received |
2028 __ mov(ecx, isolate()->factory()->next_string()); // "next" | 2032 __ mov(ecx, isolate()->factory()->next_string()); // "next" |
2029 Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize(); | 2033 Handle<Code> next_ic = isolate()->builtins()->LoadIC_Initialize(); |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2162 // Throw error if we attempt to operate on a running generator. | 2166 // Throw error if we attempt to operate on a running generator. |
2163 __ bind(&wrong_state); | 2167 __ bind(&wrong_state); |
2164 __ push(ebx); | 2168 __ push(ebx); |
2165 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2169 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
2166 | 2170 |
2167 __ bind(&done); | 2171 __ bind(&done); |
2168 context()->Plug(result_register()); | 2172 context()->Plug(result_register()); |
2169 } | 2173 } |
2170 | 2174 |
2171 | 2175 |
2172 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { | 2176 void FullCodeGenerator::EmitCreateIteratorResult(bool done) { |
2173 Label gc_required; | 2177 Label gc_required; |
2174 Label allocated; | 2178 Label allocated; |
2175 | 2179 |
2176 Handle<Map> map(isolate()->native_context()->generator_result_map()); | 2180 Handle<Map> map(isolate()->native_context()->generator_result_map()); |
2177 | 2181 |
2178 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); | 2182 __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT); |
| 2183 __ jmp(&allocated); |
| 2184 |
| 2185 __ bind(&gc_required); |
| 2186 __ Push(Smi::FromInt(map->instance_size())); |
| 2187 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 2188 __ mov(context_register(), |
| 2189 Operand(ebp, StandardFrameConstants::kContextOffset)); |
2179 | 2190 |
2180 __ bind(&allocated); | 2191 __ bind(&allocated); |
2181 __ mov(ebx, map); | 2192 __ mov(ebx, map); |
2182 __ pop(ecx); | 2193 __ pop(ecx); |
2183 __ mov(edx, isolate()->factory()->ToBoolean(done)); | 2194 __ mov(edx, isolate()->factory()->ToBoolean(done)); |
2184 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); | 2195 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); |
2185 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); | 2196 __ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx); |
2186 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 2197 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
2187 isolate()->factory()->empty_fixed_array()); | 2198 isolate()->factory()->empty_fixed_array()); |
2188 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 2199 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
2189 isolate()->factory()->empty_fixed_array()); | 2200 isolate()->factory()->empty_fixed_array()); |
2190 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); | 2201 __ mov(FieldOperand(eax, JSGeneratorObject::kResultValuePropertyOffset), ecx); |
2191 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); | 2202 __ mov(FieldOperand(eax, JSGeneratorObject::kResultDonePropertyOffset), edx); |
2192 | 2203 |
2193 // Only the value field needs a write barrier, as the other values are in the | 2204 // Only the value field needs a write barrier, as the other values are in the |
2194 // root set. | 2205 // root set. |
2195 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, | 2206 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, |
2196 ecx, edx, kDontSaveFPRegs); | 2207 ecx, edx, kDontSaveFPRegs); |
2197 | |
2198 if (done) { | |
2199 // Exit all nested statements. | |
2200 NestedStatement* current = nesting_stack_; | |
2201 int stack_depth = 0; | |
2202 int context_length = 0; | |
2203 while (current != NULL) { | |
2204 current = current->Exit(&stack_depth, &context_length); | |
2205 } | |
2206 __ Drop(stack_depth); | |
2207 } | |
2208 | |
2209 EmitReturnSequence(); | |
2210 | |
2211 __ bind(&gc_required); | |
2212 __ Push(Smi::FromInt(map->instance_size())); | |
2213 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | |
2214 __ mov(context_register(), | |
2215 Operand(ebp, StandardFrameConstants::kContextOffset)); | |
2216 __ jmp(&allocated); | |
2217 } | 2208 } |
2218 | 2209 |
2219 | 2210 |
2220 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { | 2211 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { |
2221 SetSourcePosition(prop->position()); | 2212 SetSourcePosition(prop->position()); |
2222 Literal* key = prop->key()->AsLiteral(); | 2213 Literal* key = prop->key()->AsLiteral(); |
2223 ASSERT(!key->handle()->IsSmi()); | 2214 ASSERT(!key->handle()->IsSmi()); |
2224 __ mov(ecx, Immediate(key->handle())); | 2215 __ mov(ecx, Immediate(key->handle())); |
2225 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2216 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2226 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); | 2217 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); |
(...skipping 2695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4922 *stack_depth = 0; | 4913 *stack_depth = 0; |
4923 *context_length = 0; | 4914 *context_length = 0; |
4924 return previous_; | 4915 return previous_; |
4925 } | 4916 } |
4926 | 4917 |
4927 #undef __ | 4918 #undef __ |
4928 | 4919 |
4929 } } // namespace v8::internal | 4920 } } // namespace v8::internal |
4930 | 4921 |
4931 #endif // V8_TARGET_ARCH_IA32 | 4922 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |