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