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 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 |