Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: src/arm/full-codegen-arm.cc

Issue 16801006: Allocate generator result objects before unwinding try handlers (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | src/ia32/full-codegen-ia32.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 1975 matching lines...) Expand 10 before | Expand all | Expand 10 after
1986 1986
1987 void FullCodeGenerator::VisitYield(Yield* expr) { 1987 void FullCodeGenerator::VisitYield(Yield* expr) {
1988 Comment cmnt(masm_, "[ Yield"); 1988 Comment cmnt(masm_, "[ Yield");
1989 // Evaluate yielded value first; the initial iterator definition depends on 1989 // Evaluate yielded value first; the initial iterator definition depends on
1990 // this. It stays on the stack while we update the iterator. 1990 // this. It stays on the stack while we update the iterator.
1991 VisitForStackValue(expr->expression()); 1991 VisitForStackValue(expr->expression());
1992 1992
1993 switch (expr->yield_kind()) { 1993 switch (expr->yield_kind()) {
1994 case Yield::INITIAL: 1994 case Yield::INITIAL:
1995 case Yield::SUSPEND: { 1995 case Yield::SUSPEND: {
1996 if (expr->yield_kind() == Yield::SUSPEND) {
1997 // Pop value from top-of-stack slot, box result into result register.
1998 EmitCreateIteratorResult(false);
1999 __ push(result_register());
2000 }
1996 VisitForStackValue(expr->generator_object()); 2001 VisitForStackValue(expr->generator_object());
1997 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2002 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1998 __ ldr(context_register(), 2003 __ ldr(context_register(),
1999 MemOperand(fp, StandardFrameConstants::kContextOffset)); 2004 MemOperand(fp, StandardFrameConstants::kContextOffset));
2000 2005
2001 Label resume; 2006 Label resume;
2002 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); 2007 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
2003 __ b(ne, &resume); 2008 __ b(ne, &resume);
2004 if (expr->yield_kind() == Yield::SUSPEND) { 2009 __ pop(result_register());
2005 EmitReturnIteratorResult(false); 2010 EmitReturnSequence();
2006 } else {
2007 __ pop(result_register());
2008 EmitReturnSequence();
2009 }
2010 2011
2011 __ bind(&resume); 2012 __ bind(&resume);
2012 context()->Plug(result_register()); 2013 context()->Plug(result_register());
2013 break; 2014 break;
2014 } 2015 }
2015 2016
2016 case Yield::FINAL: { 2017 case Yield::FINAL: {
2017 VisitForAccumulatorValue(expr->generator_object()); 2018 VisitForAccumulatorValue(expr->generator_object());
2018 __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 2019 __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
2019 __ str(r1, FieldMemOperand(result_register(), 2020 __ str(r1, FieldMemOperand(result_register(),
2020 JSGeneratorObject::kContinuationOffset)); 2021 JSGeneratorObject::kContinuationOffset));
2021 EmitReturnIteratorResult(true); 2022 // Pop value from top-of-stack slot, box result into result register.
2023 EmitCreateIteratorResult(true);
2024 EmitUnwindBeforeReturn();
2025 EmitReturnSequence();
2022 break; 2026 break;
2023 } 2027 }
2024 2028
2025 case Yield::DELEGATING: { 2029 case Yield::DELEGATING: {
2026 VisitForStackValue(expr->generator_object()); 2030 VisitForStackValue(expr->generator_object());
2027 2031
2028 // Initial stack layout is as follows: 2032 // Initial stack layout is as follows:
2029 // [sp + 1 * kPointerSize] iter 2033 // [sp + 1 * kPointerSize] iter
2030 // [sp + 0 * kPointerSize] g 2034 // [sp + 0 * kPointerSize] g
2031 2035
2032 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; 2036 Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
2033 // Initial send value is undefined. 2037 // Initial send value is undefined.
2034 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2038 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2035 __ b(&l_next); 2039 __ b(&l_next);
2036 2040
2037 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } 2041 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
2038 __ bind(&l_catch); 2042 __ bind(&l_catch);
2039 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2043 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2040 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2044 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2041 __ push(r3); // iter 2045 __ push(r3); // iter
2042 __ push(r0); // exception 2046 __ push(r0); // exception
2043 __ mov(r0, r3); // iter 2047 __ mov(r0, r3); // iter
2044 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" 2048 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
2045 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); 2049 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
2046 CallIC(throw_ic); // iter.throw in r0 2050 CallIC(throw_ic); // iter.throw in r0
2047 __ jmp(&l_call); 2051 __ jmp(&l_call);
2048 2052
2049 // try { received = yield result.value } 2053 // try { received = yield result.value }
2050 __ bind(&l_try); 2054 __ bind(&l_try);
2051 __ pop(r0); // result.value 2055 EmitCreateIteratorResult(false); // pop and box to r0
2052 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2056 __ PushTryHandler(StackHandler::CATCH, expr->index());
2053 const int handler_size = StackHandlerConstants::kSize; 2057 const int handler_size = StackHandlerConstants::kSize;
2054 __ push(r0); // result.value 2058 __ push(r0); // result
2055 __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g 2059 __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g
2056 __ push(r3); // g 2060 __ push(r3); // g
2057 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2061 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2058 __ ldr(context_register(), 2062 __ ldr(context_register(),
2059 MemOperand(fp, StandardFrameConstants::kContextOffset)); 2063 MemOperand(fp, StandardFrameConstants::kContextOffset));
2060 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 2064 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
2061 __ b(ne, &l_resume); 2065 __ b(ne, &l_resume);
2062 EmitReturnIteratorResult(false); 2066 __ pop(r0); // result
2067 EmitReturnSequence();
2063 __ bind(&l_resume); // received in r0 2068 __ bind(&l_resume); // received in r0
2064 __ PopTryHandler(); 2069 __ PopTryHandler();
2065 2070
2066 // receiver = iter; f = iter.next; arg = received; 2071 // receiver = iter; f = iter.next; arg = received;
2067 __ bind(&l_next); 2072 __ bind(&l_next);
2068 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2073 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2069 __ push(r3); // iter 2074 __ push(r3); // iter
2070 __ push(r0); // received 2075 __ push(r0); // received
2071 __ mov(r0, r3); // iter 2076 __ mov(r0, r3); // iter
2072 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" 2077 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next"
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
2207 // Throw error if we attempt to operate on a running generator. 2212 // Throw error if we attempt to operate on a running generator.
2208 __ bind(&wrong_state); 2213 __ bind(&wrong_state);
2209 __ push(r1); 2214 __ push(r1);
2210 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2215 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2211 2216
2212 __ bind(&done); 2217 __ bind(&done);
2213 context()->Plug(result_register()); 2218 context()->Plug(result_register());
2214 } 2219 }
2215 2220
2216 2221
2217 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { 2222 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2218 Label gc_required; 2223 Label gc_required;
2219 Label allocated; 2224 Label allocated;
2220 2225
2221 Handle<Map> map(isolate()->native_context()->generator_result_map()); 2226 Handle<Map> map(isolate()->native_context()->generator_result_map());
2222 2227
2223 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); 2228 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
2229 __ jmp(&allocated);
2230
2231 __ bind(&gc_required);
2232 __ Push(Smi::FromInt(map->instance_size()));
2233 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2234 __ ldr(context_register(),
2235 MemOperand(fp, StandardFrameConstants::kContextOffset));
2224 2236
2225 __ bind(&allocated); 2237 __ bind(&allocated);
2226 __ mov(r1, Operand(map)); 2238 __ mov(r1, Operand(map));
2227 __ pop(r2); 2239 __ pop(r2);
2228 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); 2240 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done)));
2229 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); 2241 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
2230 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2242 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2231 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2243 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2232 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2244 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2233 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2245 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2234 __ str(r2, 2246 __ str(r2,
2235 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); 2247 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset));
2236 __ str(r3, 2248 __ str(r3,
2237 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); 2249 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset));
2238 2250
2239 // Only the value field needs a write barrier, as the other values are in the 2251 // Only the value field needs a write barrier, as the other values are in the
2240 // root set. 2252 // root set.
2241 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, 2253 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
2242 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 2254 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs);
2243
2244 if (done) {
2245 // Exit all nested statements.
2246 NestedStatement* current = nesting_stack_;
2247 int stack_depth = 0;
2248 int context_length = 0;
2249 while (current != NULL) {
2250 current = current->Exit(&stack_depth, &context_length);
2251 }
2252 __ Drop(stack_depth);
2253 }
2254
2255 EmitReturnSequence();
2256
2257 __ bind(&gc_required);
2258 __ Push(Smi::FromInt(map->instance_size()));
2259 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2260 __ ldr(context_register(),
2261 MemOperand(fp, StandardFrameConstants::kContextOffset));
2262 __ jmp(&allocated);
2263 } 2255 }
2264 2256
2265 2257
2266 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2258 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2267 SetSourcePosition(prop->position()); 2259 SetSourcePosition(prop->position());
2268 Literal* key = prop->key()->AsLiteral(); 2260 Literal* key = prop->key()->AsLiteral();
2269 __ mov(r2, Operand(key->handle())); 2261 __ mov(r2, Operand(key->handle()));
2270 // Call load IC. It has arguments receiver and property name r0 and r2. 2262 // Call load IC. It has arguments receiver and property name r0 and r2.
2271 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2263 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2272 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2264 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
(...skipping 2652 matching lines...) Expand 10 before | Expand all | Expand 10 after
4925 *context_length = 0; 4917 *context_length = 0;
4926 return previous_; 4918 return previous_;
4927 } 4919 }
4928 4920
4929 4921
4930 #undef __ 4922 #undef __
4931 4923
4932 } } // namespace v8::internal 4924 } } // namespace v8::internal
4933 4925
4934 #endif // V8_TARGET_ARCH_ARM 4926 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | src/ia32/full-codegen-ia32.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698