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

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: Switch fallthrough for yield boxing 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') | no next file with comments »
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 1973 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 } 1984 }
1985 1985
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::SUSPEND:
1995 case Yield::SUSPEND: { 1995 // Pop value from top-of-stack slot; box result into result register.
1996 EmitCreateIteratorResult(false);
1997 __ push(result_register());
1998 // Fall through.
1999 case Yield::INITIAL: {
1996 VisitForStackValue(expr->generator_object()); 2000 VisitForStackValue(expr->generator_object());
1997 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2001 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
1998 __ ldr(context_register(), 2002 __ ldr(context_register(),
1999 MemOperand(fp, StandardFrameConstants::kContextOffset)); 2003 MemOperand(fp, StandardFrameConstants::kContextOffset));
2000 2004
2001 Label resume; 2005 Label resume;
2002 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex); 2006 __ CompareRoot(result_register(), Heap::kTheHoleValueRootIndex);
2003 __ b(ne, &resume); 2007 __ b(ne, &resume);
2004 if (expr->yield_kind() == Yield::SUSPEND) { 2008 __ pop(result_register());
2005 EmitReturnIteratorResult(false); 2009 EmitReturnSequence();
2006 } else {
2007 __ pop(result_register());
2008 EmitReturnSequence();
2009 }
2010 2010
2011 __ bind(&resume); 2011 __ bind(&resume);
2012 context()->Plug(result_register()); 2012 context()->Plug(result_register());
2013 break; 2013 break;
2014 } 2014 }
2015 2015
2016 case Yield::FINAL: { 2016 case Yield::FINAL: {
2017 VisitForAccumulatorValue(expr->generator_object()); 2017 VisitForAccumulatorValue(expr->generator_object());
2018 __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed))); 2018 __ mov(r1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
2019 __ str(r1, FieldMemOperand(result_register(), 2019 __ str(r1, FieldMemOperand(result_register(),
2020 JSGeneratorObject::kContinuationOffset)); 2020 JSGeneratorObject::kContinuationOffset));
2021 EmitReturnIteratorResult(true); 2021 // Pop value from top-of-stack slot, box result into result register.
2022 EmitCreateIteratorResult(true);
2023 EmitUnwindBeforeReturn();
2024 EmitReturnSequence();
2022 break; 2025 break;
2023 } 2026 }
2024 2027
2025 case Yield::DELEGATING: { 2028 case Yield::DELEGATING: {
2026 VisitForStackValue(expr->generator_object()); 2029 VisitForStackValue(expr->generator_object());
2027 2030
2028 // Initial stack layout is as follows: 2031 // Initial stack layout is as follows:
2029 // [sp + 1 * kPointerSize] iter 2032 // [sp + 1 * kPointerSize] iter
2030 // [sp + 0 * kPointerSize] g 2033 // [sp + 0 * kPointerSize] g
2031 2034
2032 Label l_catch, l_try, l_resume, l_next, l_call, l_loop; 2035 Label l_catch, l_try, l_resume, l_next, l_call, l_loop;
2033 // Initial send value is undefined. 2036 // Initial send value is undefined.
2034 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2037 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2035 __ b(&l_next); 2038 __ b(&l_next);
2036 2039
2037 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; } 2040 // catch (e) { receiver = iter; f = iter.throw; arg = e; goto l_call; }
2038 __ bind(&l_catch); 2041 __ bind(&l_catch);
2039 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2042 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2040 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2043 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2041 __ push(r3); // iter 2044 __ push(r3); // iter
2042 __ push(r0); // exception 2045 __ push(r0); // exception
2043 __ mov(r0, r3); // iter 2046 __ mov(r0, r3); // iter
2044 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" 2047 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
2045 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize(); 2048 Handle<Code> throw_ic = isolate()->builtins()->LoadIC_Initialize();
2046 CallIC(throw_ic); // iter.throw in r0 2049 CallIC(throw_ic); // iter.throw in r0
2047 __ jmp(&l_call); 2050 __ jmp(&l_call);
2048 2051
2049 // try { received = yield result.value } 2052 // try { received = yield result.value }
2050 __ bind(&l_try); 2053 __ bind(&l_try);
2051 __ pop(r0); // result.value 2054 EmitCreateIteratorResult(false); // pop and box to r0
2052 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2055 __ PushTryHandler(StackHandler::CATCH, expr->index());
2053 const int handler_size = StackHandlerConstants::kSize; 2056 const int handler_size = StackHandlerConstants::kSize;
2054 __ push(r0); // result.value 2057 __ push(r0); // result
2055 __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g 2058 __ ldr(r3, MemOperand(sp, (0 + 1) * kPointerSize + handler_size)); // g
2056 __ push(r3); // g 2059 __ push(r3); // g
2057 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2060 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2058 __ ldr(context_register(), 2061 __ ldr(context_register(),
2059 MemOperand(fp, StandardFrameConstants::kContextOffset)); 2062 MemOperand(fp, StandardFrameConstants::kContextOffset));
2060 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); 2063 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
2061 __ b(ne, &l_resume); 2064 __ b(ne, &l_resume);
2062 EmitReturnIteratorResult(false); 2065 __ pop(r0); // result
2066 EmitReturnSequence();
2063 __ bind(&l_resume); // received in r0 2067 __ bind(&l_resume); // received in r0
2064 __ PopTryHandler(); 2068 __ PopTryHandler();
2065 2069
2066 // receiver = iter; f = iter.next; arg = received; 2070 // receiver = iter; f = iter.next; arg = received;
2067 __ bind(&l_next); 2071 __ bind(&l_next);
2068 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2072 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2069 __ push(r3); // iter 2073 __ push(r3); // iter
2070 __ push(r0); // received 2074 __ push(r0); // received
2071 __ mov(r0, r3); // iter 2075 __ mov(r0, r3); // iter
2072 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" 2076 __ 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. 2211 // Throw error if we attempt to operate on a running generator.
2208 __ bind(&wrong_state); 2212 __ bind(&wrong_state);
2209 __ push(r1); 2213 __ push(r1);
2210 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2214 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2211 2215
2212 __ bind(&done); 2216 __ bind(&done);
2213 context()->Plug(result_register()); 2217 context()->Plug(result_register());
2214 } 2218 }
2215 2219
2216 2220
2217 void FullCodeGenerator::EmitReturnIteratorResult(bool done) { 2221 void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
2218 Label gc_required; 2222 Label gc_required;
2219 Label allocated; 2223 Label allocated;
2220 2224
2221 Handle<Map> map(isolate()->native_context()->generator_result_map()); 2225 Handle<Map> map(isolate()->native_context()->generator_result_map());
2222 2226
2223 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT); 2227 __ Allocate(map->instance_size(), r0, r2, r3, &gc_required, TAG_OBJECT);
2228 __ jmp(&allocated);
2229
2230 __ bind(&gc_required);
2231 __ Push(Smi::FromInt(map->instance_size()));
2232 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
2233 __ ldr(context_register(),
2234 MemOperand(fp, StandardFrameConstants::kContextOffset));
2224 2235
2225 __ bind(&allocated); 2236 __ bind(&allocated);
2226 __ mov(r1, Operand(map)); 2237 __ mov(r1, Operand(map));
2227 __ pop(r2); 2238 __ pop(r2);
2228 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done))); 2239 __ mov(r3, Operand(isolate()->factory()->ToBoolean(done)));
2229 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array())); 2240 __ mov(r4, Operand(isolate()->factory()->empty_fixed_array()));
2230 ASSERT_EQ(map->instance_size(), 5 * kPointerSize); 2241 ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
2231 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 2242 __ str(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
2232 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset)); 2243 __ str(r4, FieldMemOperand(r0, JSObject::kPropertiesOffset));
2233 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset)); 2244 __ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
2234 __ str(r2, 2245 __ str(r2,
2235 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset)); 2246 FieldMemOperand(r0, JSGeneratorObject::kResultValuePropertyOffset));
2236 __ str(r3, 2247 __ str(r3,
2237 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset)); 2248 FieldMemOperand(r0, JSGeneratorObject::kResultDonePropertyOffset));
2238 2249
2239 // Only the value field needs a write barrier, as the other values are in the 2250 // Only the value field needs a write barrier, as the other values are in the
2240 // root set. 2251 // root set.
2241 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset, 2252 __ RecordWriteField(r0, JSGeneratorObject::kResultValuePropertyOffset,
2242 r2, r3, kLRHasBeenSaved, kDontSaveFPRegs); 2253 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 } 2254 }
2264 2255
2265 2256
2266 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2257 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2267 SetSourcePosition(prop->position()); 2258 SetSourcePosition(prop->position());
2268 Literal* key = prop->key()->AsLiteral(); 2259 Literal* key = prop->key()->AsLiteral();
2269 __ mov(r2, Operand(key->handle())); 2260 __ mov(r2, Operand(key->handle()));
2270 // Call load IC. It has arguments receiver and property name r0 and r2. 2261 // Call load IC. It has arguments receiver and property name r0 and r2.
2271 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2262 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
2272 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2263 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
(...skipping 2652 matching lines...) Expand 10 before | Expand all | Expand 10 after
4925 *context_length = 0; 4916 *context_length = 0;
4926 return previous_; 4917 return previous_;
4927 } 4918 }
4928 4919
4929 4920
4930 #undef __ 4921 #undef __
4931 4922
4932 } } // namespace v8::internal 4923 } } // namespace v8::internal
4933 4924
4934 #endif // V8_TARGET_ARCH_ARM 4925 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/full-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698